سؤال

لقد قمت بتجربة تعبيرات لامدا في الأكسجين.تعبير لامدا العودي البسيط جدًا لحساب رقم فيبوناتشي:

var fib : Func<int32, int32>;
fib := n -> iif(n > 1, fib(n - 1) + fib(n - 2), n);
fib(3);

عندما أقوم بتشغيل هذا الرمز أحصل على استثناء nullreference.أي أفكار حول ما أفعله خطأ؟

هل كانت مفيدة؟

المحلول

وأنت لم تفعل شيئا خاطئا. إذا كان أي شيء، يجب على المترجم يحذرك حول استخدام أكذوبة، متغير غير معين، داخل الجسم لامدا.

ولكن المترجم يجب أن التقاط أكذوبة كموقع، بحيث عندما يكمل المهمة ويتم استدعاء مندوب في وقت لاحق، تم تعيينه بشكل صحيح أكذوبة ويجب أن تعمل العودية كما هو متوقع.

والسبب الأكثر وضوحا من الممكن للفشل هو أن بريزم لا التقاط المواقع، ولكن القيم، التي ستكون unintuitive بشكل فاضح وعلى خلاف مع كل تنفيذ إغلاق آخرين في لغات غير نقية.

وعلى سبيل المثال، حاول هذا الرمز في جافا سكريبت (مخالف للتأكيد كريج في تعليقات على هذه الوظيفة، وجافا سكريبت أيضا يلتقط المواقع، وليس القيم):

<html>
<head>
<script language='javascript'>
function main()
{
    var x = 1;
    var f = function() { return x; };
    alert(f());
    x = 2;
    alert(f());
}
</script>
</head>
<body>
<input type=button onclick="javascript:main()"></input>
</body>
</html>

ومربعات حالة تأهب بعد النقر على زر إظهار 1 و 2 على التوالي، في حين التالية دلالات بريزم / الأكسجين فإنها تظهر 1 في المرتين.

نصائح أخرى

وستيف:

وعلى ما يبدو تم تناول مسألة في دلفي بريزم 2010. وتعمل نموذج التعليمات البرمجية التالية في الافراج عن مسؤول.

 var fib : Func<int32, int32>;
 fib := n -> iif(n > 1, fib(n - 1) + fib(n - 2), n);
 var i := fib(9); //1,1,2,3,5,8,13,21,34
 MessageBox.Show(i.ToString);

ووMESSAGEBOX يظهر القيمة 34.

وردا على سؤال جيرون، تم تشغيل هذا الرمز في النص الأصلي، بناء الافراج عن مسؤول، 3.0.21.661.

وكحل مؤقت يمكنك استخدامها:

var f := new class(f: Tfib := nil);
f.f := method(n : Int32): Int32
begin
  if n > 1 then  
    Result := f.f(n-1) + f.f(n-2)
  else
    Result := n;
end;
f.f(3);

وبريزم يعالج القبض على المتغيرات المحلية بشكل مختلف ثم أصلي دلفي أو C #. في تلك 2 سيتم تعيين جميع الإشارات في التعليمات البرمجية تلك السكان المحليين إلى حقول من الفئة التي تم إنشاؤها مترجم التي ستعقد طريقة دون الافصاح عن هويتك. في المنشور، هذه السكان المحليين البقاء السكان المحليين العاديين، ولكن يتم تعيين مجالات هذه الحقول المخفية عند مثيل طريقة المجهول.

واحد طريقة للحصول على امدا العودية، سيكون لاستخدام نوع مرجع لعقد امدا بالنسبة لك.

كل هذا يبدو أكثر تعقيدا بكثير ثم هو عليه حقا.
2 طرق لإنجاز هدفك:
1)


    var fib := new class(Call : Func<Integer, Integer> := nil);  
    fib.Call := n -> iif(n > 1, fib.Call(n - 1) + fib.Call(n - 2), n);  
    var x := fib.Call(3);  

2) عندما كنت لا تريد أن يكون إشارة إلى هذا المجمع، يمكنك أن تفعل ذلك كما يلي:


    var fib : Func;  
    with fibWrapper := new class(Call : Func<Integer, Integer> := nil) do  
    begin  
        fibWrapper.Call := n -> iif(n > 1, fibWrapper.Call(n - 1) + fibWrapper.Call(n - 2), n);  
        fib := fibWrapper.Call;  
    end;

وراجع للشغل، والسبب وراء بريزم عدم اتباع C # هنا، هو أن للخيوط وحلقة، وهذا إعادة استخدام فار القبض يجعل لمشاكل وقت التشغيل غريبة الصعبة. في بريزم، وألقت القبض على يلتقط حقا لحظة تعيين طريقة مجهول أو امدا. الذي لديه لمسة immuatble معين لذلك ...

وابتهاج، روبرت

هل ينطبق الأمر نفسه على الأساليب المجهولة؟أعتقد أنه كذلك، لكن لا يمكنني معرفة بناء الجملة لتشغيل هذا

  var f : Tfib;
  f := method(n : Int32): Int32
  begin
    if n > 1 then  
      Result := f(n-1) + f(n-2)
    else
      Result := n;
  end;

يحرر

نعم هو كذلك.

  var f := new class(call : TFib := nil);
  f.call := method(n : Int32): Int32
  begin
    if n > 1 then  
      Result := f.call(n-1) + f.call(n-2)
    else
      Result := n;
  end;

لقد حاولت أيضًا تعيين المتغير:

var fib : Func<int32, int32> := nil;
fib := n -> iif(n > 1, fib(n - 1) + fib(n - 2), n);
fib(3);

لا يزال دون حظ.

بدافع الفضول حاولت شيئًا مشابهًا باستخدام طرق مجهولة.

لقد قمت بشكل أساسي بتنفيذ بحث متعمق أولاً على رسم بياني غير دوري مباشر باستخدام طريقة مجهولة متكررة:

var dfs : dfsmethod;
dfs := method(Vertex : IVertex)
begin
  var IsDone : Boolean;
  Visited[Vertex.Key] := True;
  aMethod(Vertex.Key, Vertex.Weight, var IsDone);  //PreVisit
  if IsDone then Exit;
  for each Successor in Vertex.Successors do
    if not Visited[Successor.Key] then
      dfs(Successor);
end;
dfs(InternalGetVertex(aStart));

تم تجميع هذا، ولكن حصلت على نفس الخطأ.NullReferenceException.

لقد حاولت أيضًا إعادة تنفيذ فيبوناتشي كطريقة مجهولة متكررة:

  var f : Tfib;
  f := method(n : Int32): Int32
  begin
    if n > 1 then  
      Result := f(n-1) + f(n-2)
    else
      Result := n;
  end;
  f(3)

مرة أخرى نفس المشكلة!دائمًا في التكرار الثاني (أيأول مكالمة متكررة)

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top