emacs-orgmode@gnu.org archives
 help / color / mirror / code / Atom feed
* [Babel] Interpreting results as tables and (eval)'uation of them
@ 2011-02-13 20:37 Dan Amlund Thomsen
  2011-02-14 18:58 ` Eric Schulte
  0 siblings, 1 reply; 3+ messages in thread
From: Dan Amlund Thomsen @ 2011-02-13 20:37 UTC (permalink / raw)
  To: emacs-orgmode

I've encountered some weird, possible buggy, behavior when
interpreting results as tables (tested with python, scheme and lisp).

* Item 1: Interpreting result as table
With ":results value" the result is interpreted as a table if
possible, but with ":results output" it isn't. This happens with
python, lisp and scheme, but not with c.

The documentation suggests both value and output results should be
interpreted as a table if possible.

"By default, results are inserted as either a table or scalar
depending on their value." [http://orgmode.org/manual/results.html]

#+begin_src python :results output
  print "'(1 2)"
#+end_src

#+results:
: '(1 2)

#+begin_src python :results value
  return "'(1 2)"
#+end_src

#+results:
| 1 | 2 |

* Item 2: Evaluating list results
When a result is interpreted as a list, the list is (eval)'ed. This
happens in non-lisp languages (c, python) but not in lisp languages
(lisp, scheme).

In my opinion the lists should not be evaluated, but
'org-babel-script-escape' and 'org-babel-read' suggests it is intended
behavior.

Is this a bug or a feature?

#+begin_src c++ :includes <stdio.h>
  printf("(1 2)");
#+end_src

Returns the error "Invalid function: 1".

The correct approach is:
#+begin_src c++ :includes <stdio.h>
  printf("(list 1 2)");
#+end_src

#+results:
| 1 | 2 |

With lisp the list is not evaluated (note that "'(1 2)" results in
"(1 2)").
#+begin_src lisp
  '(1 2)
#+end_src

#+results:
| 1 | 2 |

* Item 3: Checking if result is a list is not safe
Mismatched parenthesis and bad characters causes errors. I suggest
showing the raw result if the result is not a valid list.

I'm not sure if this is a bug or not. These error messages could be
helpful in debugging code when trying to output a list that needs to
be evaluated. Although the final output of the (invalid) list could
also be helpful with debugging.

#+begin_src c++ :includes <stdio.h>
  printf("(");
#+end_src
Returns the error: End of file during parsing

#+begin_src python 
  return "(list #)"
#+end_src
Returns the error: Invalid read syntax: "#"

Here are some possible solutions:
#+begin_src emacs-lisp
  (defun org-babel-safe-read-dont-eval (str)
    "Converts string into a list. Elements are converted into
  strings to prevent read errors from special characters."
    (let ((str (replace-regexp-in-string
                "\\([^() \f\t\n\r\v]+\\)" "\"\\1\""str)))
      (condition-case nil
          (read str)
        (error (concat "\"" str "\"")))))

  (org-babel-safe-read-dont-eval "(1 1#123 1)")  
#+end_src

#+results:
| 1 | 1#123 | 1 |

#+begin_src emacs-lisp
  (defun org-babel-safe-read-do-eval (str)
    "Converts string into a evaluated list."
    (condition-case nil
        (eval (read str))
      (error (concat "\"" str "\""))))

  (org-babel-safe-read-do-eval "(1 1#123 1)")
#+end_src

#+results:
: "(1 1#123 1)"

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [Babel] Interpreting results as tables and (eval)'uation of them
  2011-02-13 20:37 [Babel] Interpreting results as tables and (eval)'uation of them Dan Amlund Thomsen
@ 2011-02-14 18:58 ` Eric Schulte
  2011-03-06 17:59   ` Eric Schulte
  0 siblings, 1 reply; 3+ messages in thread
From: Eric Schulte @ 2011-02-14 18:58 UTC (permalink / raw)
  To: danamlund; +Cc: emacs-orgmode

Hi Dan,

Dan Amlund Thomsen <danamlund@gmail.com> writes:

> I've encountered some weird, possible buggy, behavior when
> interpreting results as tables (tested with python, scheme and lisp).
>
> * Item 1: Interpreting result as table
> With ":results value" the result is interpreted as a table if
> possible, but with ":results output" it isn't. This happens with
> python, lisp and scheme, but not with c.
>
> The documentation suggests both value and output results should be
> interpreted as a table if possible.
>
> "By default, results are inserted as either a table or scalar
> depending on their value." [http://orgmode.org/manual/results.html]
>
> #+begin_src python :results output
>   print "'(1 2)"
> #+end_src
>
> #+results:
> : '(1 2)
>
> #+begin_src python :results value
>   return "'(1 2)"
> #+end_src
>
> #+results:
> | 1 | 2 |
>

Yes, this assumption (":results output" implies ":results scalar") is
built into many of the language-specific modes and should probably be
removed.

>
> * Item 2: Evaluating list results
> When a result is interpreted as a list, the list is (eval)'ed. This
> happens in non-lisp languages (c, python) but not in lisp languages
> (lisp, scheme).
>
> In my opinion the lists should not be evaluated, but
> 'org-babel-script-escape' and 'org-babel-read' suggests it is intended
> behavior.
>
> Is this a bug or a feature?
>
> #+begin_src c++ :includes <stdio.h>
>   printf("(1 2)");
> #+end_src
>
> Returns the error "Invalid function: 1".
>
> The correct approach is:
> #+begin_src c++ :includes <stdio.h>
>   printf("(list 1 2)");
> #+end_src
>
> #+results:
> | 1 | 2 |
>
> With lisp the list is not evaluated (note that "'(1 2)" results in
> "(1 2)").
> #+begin_src lisp
>   '(1 2)
> #+end_src
>
> #+results:
> | 1 | 2 |
>

Hmm, I'll have to take a closer look at `org-babel-script-escape'.
Automatic evaluation of lispy return strings should not be the default
behavior as I doubt that is what users would expect.  Maybe we shouldn't
be calling `org-babel-read' (which *is* supposed to evaluate lispy
strings) from `org-babel-script-escape'.  Thanks for pointing this out.

>
> * Item 3: Checking if result is a list is not safe
> Mismatched parenthesis and bad characters causes errors. I suggest
> showing the raw result if the result is not a valid list.
>
> I'm not sure if this is a bug or not. These error messages could be
> helpful in debugging code when trying to output a list that needs to
> be evaluated. Although the final output of the (invalid) list could
> also be helpful with debugging.
>
> #+begin_src c++ :includes <stdio.h>
>   printf("(");
> #+end_src
> Returns the error: End of file during parsing
>
> #+begin_src python 
>   return "(list #)"
> #+end_src
> Returns the error: Invalid read syntax: "#"
>

Agreed, in these cases the raw scalar result should be returned.  Again,
thanks for pointing these out.

>
> Here are some possible solutions:
> #+begin_src emacs-lisp
>   (defun org-babel-safe-read-dont-eval (str)
>     "Converts string into a list. Elements are converted into
>   strings to prevent read errors from special characters."
>     (let ((str (replace-regexp-in-string
>                 "\\([^() \f\t\n\r\v]+\\)" "\"\\1\""str)))
>       (condition-case nil
>           (read str)
>         (error (concat "\"" str "\"")))))
>
>   (org-babel-safe-read-dont-eval "(1 1#123 1)")  
> #+end_src
>
> #+results:
> | 1 | 1#123 | 1 |
>
> #+begin_src emacs-lisp
>   (defun org-babel-safe-read-do-eval (str)
>     "Converts string into a evaluated list."
>     (condition-case nil
>         (eval (read str))
>       (error (concat "\"" str "\""))))
>
>   (org-babel-safe-read-do-eval "(1 1#123 1)")
> #+end_src
>
> #+results:
> : "(1 1#123 1)"
>

Yes, these code snippets seem to be headed in the right direction.

Much appreciated -- Eric

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [Babel] Interpreting results as tables and (eval)'uation of them
  2011-02-14 18:58 ` Eric Schulte
@ 2011-03-06 17:59   ` Eric Schulte
  0 siblings, 0 replies; 3+ messages in thread
From: Eric Schulte @ 2011-03-06 17:59 UTC (permalink / raw)
  To: danamlund; +Cc: emacs-orgmode

Hi,

Just to update, two of the three problems mentioned in this thread have
now been fixed.  The two global issues (i.e. 2. and 3.), meaning that if
the results are not a well formed list, or are not eval-able, then they
are returned literally, allowing things like passing tuples back from
python etc...

The remaining issue (":results output" → ":results scalar") is a
language implementation specific issue, and will have to be fixed in
those languages in which is occurs.

Best -- Eric

Note: that results may still be eval'd, e.g.,

#+begin_src python :results value
  return "[1, 2]"
#+end_src

#+results:
| 1 | 2 |

and

#+begin_src python :results value
  return [1, 2]
#+end_src

#+results:
| 1 | 2 |

There is no way to differentiate between the two code blocks above in a
general way, however something like the following may be used to force a
string interpretation (note: I don't know python so there's probably a
better way).

#+begin_src python :results value
  return "%r" % "[1 2]"
#+end_src

#+results:
: [1 2]

Maybe this behavior should be changed, but I'm not sure how...

A perhaps slightly more unsettling version of the above would be
#+begin_src python :results value
  return "(mapcar (lambda (el) (+ 1 el)) '(1 2))"
#+end_src

#+results:
| 2 | 3 |

"Eric Schulte" <schulte.eric@gmail.com> writes:

> Hi Dan,
>
> Dan Amlund Thomsen <danamlund@gmail.com> writes:
>
>> I've encountered some weird, possible buggy, behavior when
>> interpreting results as tables (tested with python, scheme and lisp).
>>
>> * Item 1: Interpreting result as table
>> With ":results value" the result is interpreted as a table if
>> possible, but with ":results output" it isn't. This happens with
>> python, lisp and scheme, but not with c.
>>
>> The documentation suggests both value and output results should be
>> interpreted as a table if possible.
>>
>> "By default, results are inserted as either a table or scalar
>> depending on their value." [http://orgmode.org/manual/results.html]
>>
>> #+begin_src python :results output
>>   print "'(1 2)"
>> #+end_src
>>
>> #+results:
>> : '(1 2)
>>
>> #+begin_src python :results value
>>   return "'(1 2)"
>> #+end_src
>>
>> #+results:
>> | 1 | 2 |
>>
>
> Yes, this assumption (":results output" implies ":results scalar") is
> built into many of the language-specific modes and should probably be
> removed.
>
>>
>> * Item 2: Evaluating list results
>> When a result is interpreted as a list, the list is (eval)'ed. This
>> happens in non-lisp languages (c, python) but not in lisp languages
>> (lisp, scheme).
>>
>> In my opinion the lists should not be evaluated, but
>> 'org-babel-script-escape' and 'org-babel-read' suggests it is intended
>> behavior.
>>
>> Is this a bug or a feature?
>>
>> #+begin_src c++ :includes <stdio.h>
>>   printf("(1 2)");
>> #+end_src
>>
>> Returns the error "Invalid function: 1".
>>
>> The correct approach is:
>> #+begin_src c++ :includes <stdio.h>
>>   printf("(list 1 2)");
>> #+end_src
>>
>> #+results:
>> | 1 | 2 |
>>
>> With lisp the list is not evaluated (note that "'(1 2)" results in
>> "(1 2)").
>> #+begin_src lisp
>>   '(1 2)
>> #+end_src
>>
>> #+results:
>> | 1 | 2 |
>>
>
> Hmm, I'll have to take a closer look at `org-babel-script-escape'.
> Automatic evaluation of lispy return strings should not be the default
> behavior as I doubt that is what users would expect.  Maybe we shouldn't
> be calling `org-babel-read' (which *is* supposed to evaluate lispy
> strings) from `org-babel-script-escape'.  Thanks for pointing this out.
>
>>
>> * Item 3: Checking if result is a list is not safe
>> Mismatched parenthesis and bad characters causes errors. I suggest
>> showing the raw result if the result is not a valid list.
>>
>> I'm not sure if this is a bug or not. These error messages could be
>> helpful in debugging code when trying to output a list that needs to
>> be evaluated. Although the final output of the (invalid) list could
>> also be helpful with debugging.
>>
>> #+begin_src c++ :includes <stdio.h>
>>   printf("(");
>> #+end_src
>> Returns the error: End of file during parsing
>>
>> #+begin_src python 
>>   return "(list #)"
>> #+end_src
>> Returns the error: Invalid read syntax: "#"
>>
>
> Agreed, in these cases the raw scalar result should be returned.  Again,
> thanks for pointing these out.
>
>>
>> Here are some possible solutions:
>> #+begin_src emacs-lisp
>>   (defun org-babel-safe-read-dont-eval (str)
>>     "Converts string into a list. Elements are converted into
>>   strings to prevent read errors from special characters."
>>     (let ((str (replace-regexp-in-string
>>                 "\\([^() \f\t\n\r\v]+\\)" "\"\\1\""str)))
>>       (condition-case nil
>>           (read str)
>>         (error (concat "\"" str "\"")))))
>>
>>   (org-babel-safe-read-dont-eval "(1 1#123 1)")  
>> #+end_src
>>
>> #+results:
>> | 1 | 1#123 | 1 |
>>
>> #+begin_src emacs-lisp
>>   (defun org-babel-safe-read-do-eval (str)
>>     "Converts string into a evaluated list."
>>     (condition-case nil
>>         (eval (read str))
>>       (error (concat "\"" str "\""))))
>>
>>   (org-babel-safe-read-do-eval "(1 1#123 1)")
>> #+end_src
>>
>> #+results:
>> : "(1 1#123 1)"
>>
>
> Yes, these code snippets seem to be headed in the right direction.
>
> Much appreciated -- Eric

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2011-03-06 17:59 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-02-13 20:37 [Babel] Interpreting results as tables and (eval)'uation of them Dan Amlund Thomsen
2011-02-14 18:58 ` Eric Schulte
2011-03-06 17:59   ` Eric Schulte

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).