سؤال
وأنا الغريب لمعرفة ما إذا كان 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"))