سؤال

لقد اكتشفت ذلك InString[] لا يعمل في MathLink الوضع عند إرسال المدخلات مع EnterExpressionPacket header.لذلك أحتاج إلى تحديد وظيفتي الخاصة التي تُرجع سطر الإدخال السابق.إحدى الطرق التي قمت بتطويرها here لا يعمل في بعض الحالات:

In[1]:= Unevaluated[2 + 2]
With[{line = $Line - 1}, HoldForm[In[line]]] /. (DownValues[In])
Out[1]= Unevaluated[2 + 2]
Out[2]= 2 + 2

هذا بسبب RuleDelayed لا يملك HoldAllComplete يصف.تؤدي إضافة هذه السمة إلى جعل الأمر موافقًا:

In[1]:= Unprotect[RuleDelayed];
SetAttributes[RuleDelayed, HoldAllComplete];
Protect[RuleDelayed];
Unevaluated[2 + 2]
With[{line = $Line - 1}, HoldForm[In[line]]] /. DownValues[In]

Out[4]= Unevaluated[2 + 2]

Out[5]= Unevaluated[2 + 2]

لكن تعديل الوظائف المضمنة بشكل عام ليس فكرة جيدة.هل هناك طريقة أفضل للقيام بذلك؟

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

المحلول

ويبدو أنني قد حلت المشكلة.هنا هي الوظيفة:

In[1]:=
getLastInput := Module[{num, f},
    f = Function[{u, v},
        {u /. {In -> num, HoldPattern -> First}, HoldForm[v]}, HoldAllComplete];
    First@Cases[
        Block[{RuleDelayed = f}, DownValues[In]],
        {$Line - 1, x_} -> x, {1}, 1]]

In[2]:=
Unevaluated[2+2]
getLastInput

Out[2]=
Unevaluated[2+2]

Out[3]=
Unevaluated[2+2]

ولقد حصلت للتو على إجابة السؤال InString في MathLink الوضع من تود جايلي (أبحاث ولفرام):

يتم تعيين التعليمات فقط عند استخدام EnterTextPacket ، وليس enterexpressionpacket.لا يوجد شكل سلسلة من الإدخال عند إرسال enterexpressionpacket (الذي يكون محتواه ، بحكم تعريفه ، تعبيرًا بالفعل).

يحرر:

لقد وجدت للتو أن الكود الخاص بي لا يعمل مع تعبيرات الإدخال ذات الرأس Evaluate.الحل هو الاستبدال HoldForm بواسطة HoldComplete في الكود الخاص بي:

getLastInput := Module[{num, f},
    f = Function[{u, v},
        {u /. {In -> num, HoldPattern -> First}, HoldComplete[v]}, HoldAllComplete];
    First@Cases[
        Block[{RuleDelayed = f}, DownValues[In]],
        {$Line - 1, x_} -> x, {1}, 1]]

هذا يعمل بشكل جيد.هناك نهج آخر يتمثل في إلغاء الحماية HoldForm وإعداد السمة HoldAllComplete عليه.أنا أتساءل لماذا HoldForm لا يملك هذه السمة بشكل افتراضي؟

تحرير 2:

في التعليقات على السؤال الرئيسي، اقترح ليونيد شيفرين حلاً أفضل بكثير:

getLastInput := 
 Block[{RuleDelayed},SetAttributes[RuleDelayed,HoldAllComplete];
  With[{line=$Line-1},HoldComplete[In[line]]/.DownValues[In]]]

انظر التعليقات للحصول على التفاصيل.

تحرير 3:يمكن تحسين الكود الأخير عن طريق الاستبدال HoldComplete بواسطة مزدوجة HoldForm:

getLastInput := 
 Block[{RuleDelayed},SetAttributes[RuleDelayed,HoldAllComplete];
  With[{line=$Line-1},HoldForm@HoldForm[In[line]]/.DownValues[In]]]

الفكرة مأخوذة من العرض الذي قدمه روبي فيليجاس من شركة Wolfram Research في مؤتمر المطورين عام 1999.راجع القسم الفرعي "الحجز الكامل:متغير غير قابل للطباعة من HoldComplete (تمامًا كما هو الحال مع HoldForm)" في "العمل مع التعبيرات غير المقيَّمة" تم نشر دفتر الملاحظات هنا.

نصائح أخرى

سأستخدم $Pre و $Line لهذا؛على عكس $PreRead, ، يتم تطبيقه على تعبيرات الإدخال, ، وليس إدخال سلاسل أو نماذج مربعة.كل ما تحتاجه هو تعيين وظيفة تحتوي على HoldAllComplete السمة، مثل هذه التي قمت بتعديلها من المثال الموجود في الوثائق:

SetAttributes[saveinputs, HoldAllComplete];
saveinputs[new_] :=
 With[{line = $Line},
  inputs[line] = HoldComplete[new]; new]
$Pre = saveinputs;

لقد اختبرت هذا باستخدام MathLink، ويبدو أن السلوك هو ما تريده (لقد حذفت بعضًا من النص لتسليط الضوء على النقطة الأساسية):

In[14]:= LinkWrite[link,
 Unevaluated[
  EnterExpressionPacket[
   SetAttributes[saveinputs, HoldAllComplete];
   saveinputs[new_] :=
    With[{line = $Line},
     inputs[line] = HoldComplete[new]; new];
   $Pre = saveinputs;]]]

In[15]:= LinkRead[link]
Out[15]= InputNamePacket["In[2]:= "]

In[20]:= LinkWrite[link,
 Unevaluated[EnterExpressionPacket[Evaluate[1 + 1]]]]

In[21]:= LinkRead[link]
Out[21]= OutputNamePacket["Out[2]= "]

In[21]:= LinkRead[link]
Out[21]= ReturnExpressionPacket[2]

In[24]:= LinkWrite[link, Unevaluated[EnterExpressionPacket[DownValues[inputs]]]]

In[26]:= LinkRead[link]
Out[26]= ReturnExpressionPacket[
  {HoldPattern[inputs[2]] :> HoldComplete[Evaluate[1 + 1]], 
   HoldPattern[inputs[3]] :> HoldComplete[DownValues[inputs]]}]

لقد وجدت للتو طريقة أبسط ولكنها خطيرة:

In[3]:= Unevaluated[2 + 2]
Trace[In[$Line - 1]] // Last
Trace[In[$Line - 1]] // Last

Out[3]= Unevaluated[2 + 2]

Out[4]= Unevaluated[2 + 2]

During evaluation of In[3]:= $RecursionLimit::reclim: Recursion depth of 256 exceeded. >>

During evaluation of In[3]:= $RecursionLimit::reclim: Recursion depth of 256 exceeded. >>

During evaluation of In[3]:= $IterationLimit::itlim: Iteration limit of 4096 exceeded. >>

Out[5]= Hold[In[$Line-1]]

هل يعرف أحد طريقة لجعلها آمنة؟

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