سؤال

وأنا الغريب لمعرفة ما إذا كان R يمكن استخدام وظيفة eval() لتنفيذ العمليات الحسابية التي تقدمها على سبيل المثال سلسلة.

وهذه هي حالة شائعة:

eval("5+5")

ولكن، بدلا من 10 أحصل على:

[1] "5+5"

وأي حل؟

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

المحلول

وظيفة eval() بتقييم تعبير، ولكن "5+5" هو سلسلة، وليس تعبيرا. استخدام parse() مع text=<string> لتغيير السلسلة في تعبير:

> eval(parse(text="5+5"))
[1] 10
> class("5+5")
[1] "character"
> class(parse(text="5+5"))
[1] "expression"

ودعوة eval() استدعاء العديد من السلوكيات، وبعضها ليس واضحا على الفور:

> class(eval(parse(text="5+5")))
[1] "numeric"
> class(eval(parse(text="gray")))
[1] "function"
> class(eval(parse(text="blue")))
Error in eval(expr, envir, enclos) : object 'blue' not found

وانظر أيضا tryCatch .

نصائح أخرى

ويمكنك استخدام وظيفة parse() لتحويل الأحرف إلى تعبير. تحتاج إلى تحديد أن الإدخال النص، لأن تحليل تتوقع الملف بشكل افتراضي:

eval(parse(text="5+5"))

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

وو(ربما) اتصال فقط هو عبر parse(text = ....) وينبغي لجميع المبرمجين جيدة R يعرفون أن هذا نادرا ما يكون وسيلة فعالة أو آمنة لتعبيرات بناء (أو المكالمات). بدلا معرفة المزيد عن substitute()، quote()، وربما قوة باستخدام do.call(substitute, ......).

fortunes::fortune("answer is parse")
# If the answer is parse() you should usually rethink the question.
#    -- Thomas Lumley
#       R-help (February 2005)

وDec.2017: طيب، هنا مثال (في تصريحات، ليس هناك لطيفة تنسيق):

q5 <- quote(5+5)
str(q5)
# language 5 + 5

e5 <- expression(5+5)
str(e5)
# expression(5 + 5)

واذا كان لديك أكثر من ذوي الخبرة ستعرف أن q5 هو "call" في حين e5 هو "expression"، وحتى أن e5[[1]] مطابق لq5:

identical(q5, e5[[1]])
# [1] TRUE

وبدلا من ذلك، يمكنك استخدام evals من حزمة pander بلدي لإخراج القبض وجميع التحذيرات والأخطاء ورسائل أخرى إلى جانب النتائج الأولية:

> pander::evals("5+5")
[[1]]
$src
[1] "5 + 5"

$result
[1] 10

$output
[1] "[1] 10"

$type
[1] "numeric"

$msg
$msg$messages
NULL

$msg$warnings
NULL

$msg$errors
NULL


$stdout
NULL

attr(,"class")
[1] "evals"

وهذه الأيام يمكنك أيضا استخدام وظيفة lazy_eval من حزمة lazyeval.

> lazyeval::lazy_eval("5+5")
[1] 10

وعلى نحو مماثل باستخدام rlang:

eval(parse_expr("5+5"))
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top