Lambda makrosu nasıl lambda oluşturur?


20

GitHub'da bu kod parçasını buldum ama tam olarak anlamadım:

#define lambda(ret_type, _body) ({ ret_type _ _body _; })

Sonra:

int (*max)(int, int) = lambda(int,
                             (int x, int y) {
                                 return x > y ? x : y;
                             });

int max_value = max(1, 2);
// max_value is 2

Alt çizgi ne yapıyor #defineve bir işlev işaretçisi nasıl geri dönüyor?


7
gcc -ENe yaptığını görmek için sadece makroyu genişletmeyi denediniz mi (örn. İle )?
Yararsız

5
Lütfen genişlemeye bakın godbolt.org/z/C5TLWj Sonucu anlamak kolay değil
Eugene Sh.

2
Bu kodu aldığınız yerin çevresindeki yorumlara dayanarak bildiğinizi varsayıyorum, ancak bu, iç içe işlevler için GCC uzantılarına güveniyor.
Thomas Jager

4
@EugeneSh. GCC'nin iç içe işlevlerini kullanarak bir işlev işaretçisini başlatır. Orijinal kod buradan . Bu proje bugün Hacker News'te paylaşıldı.
Thomas Jager

4
@EugeneSh. İki GCC uzantısının birleşimidir: iç içe işlevler ve ifadelerde bileşik ifadeler . Yuvalanmış işlev, bileşik ifadesinin içinde görünür.
interjay

Yanıtlar:


10

Bu makroyu kullanarak,

int (*max)(int, int) = lambda(int,
                             (int x, int y) {
                                 return x > y ? x : y;
                             });

genişler:

int (*max)(int, int) = ({
    int _ (int x, int y) { return x > y ? x : y; }
    _;
});

Kıvırcık parantezlerde, bu , istenen işlemi gerçekleştiren bir işlev oluşturmak için GCC'nin İç İçe İşlevlerini kullanır . İç kapsamda adı vardır _.

Daha sonra, interjay tarafından belirtildiği gibi, GCC'nin İfade İfadeleri kullanılır. Etkili olarak, işlev _işaretçiye atanır max.

Böyle bir makro kullanılmıyorsa, bu farklı yazılabilir ve şu şekilde kullanılabilir:

int val1 = 4;
int val2 = -30;

int perform_operation(int (*op)(int, int)) {
    int new_val = op(val1, val2);
    val1 = val2;
    val2 = new_val;
    return new_val;
}

int enclosing_function (void) {
    // Create max "lambda"
    int (*max)(int, int);
    {
        // Curly braces limit the scope of _
        int _ (int x, int y) { return x > y ? x : y; }
        max = _;
    }

    return perform_operation(max);
}

Üç yöntem bu kod örneğinde karşılaştırılabilir .


Makro,
gcc'de


@P__J__ Cevabımın sonuna bu makronun kullanıldığını gösteren bir örnek ekledim.
Thomas Jager

Neden max(4, -30);yerine yapamıyorsun apply_binary_op(max, 4, -30);?
SS Anne

1
"İfadelerdeki Bileşik İfadeler", "ifade ifadeleri" olarak adlandırılır. Bir şeye atanabilen (ör.) Bir değere sahip ifadeler.
Peter Cordes

7

Buna ifade ifadesi denir ve bir "lambda" (veya iç içe işlev ) oluşturur ve buna bir işaretçi döndürür. GNU C'ye özgüdür.

Makro aşağıdakilere genişler:

int (*max)(int, int) = ({ int _ (int x, int y) { return x > y ? x : y; } _; })

_Sonunda bir gibidir return.

Alt çizgi aslında oluşturulan ve "döndürülen" işlevin adıdır. Nadiren kullanılan bir tanımlayıcı olduğu için kullanılır (iyi bir nedenle; _büyük olasılıkla mümkün olan en az tanımlayıcı tanımlayıcıdır).

İfade ifadesinin kullanılma nedeni, ifade ifadesinin _kapsamı çıktıktan sonra tanımlanmayacaktır.

Yani, makrodan geçerek:

#define lambda(ret_type, _body) ({ ret_type _ _body _; })

ret_type"lambda" nın dönüş türüdür. _nadir bir tanımlayıcı adı olduğu için içinde kullanılan işlevin adıdır. _bodyfonksiyonun argümanlarından ve gövdesinden oluşur. Sondaki _"lambda" yı döndürür.

Bu kod Let's Destroy C'de (uygun bir isimdir) bulunur. Kullanmamalısın. Kodunuzun yalnızca GNU C uzantılarını destekleyen derleyicilerde çalışmasını sağlar. Bunun yerine, bir işlev veya makro yazın.

Bunun gibi yapılar çok kullanıyorsanız veya daha fazla özellik istiyorsanız, C ++ kullanmanızı öneririm. C ++ ile buna benzer bir şey yapabilir ve taşınabilir koda sahip olabilirsiniz.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.