crystal-lang / crystal

The Crystal Programming Language
https://crystal-lang.org
Apache License 2.0
19.5k stars 1.62k forks source link

`p` vs. `p!` with kwargs #10695

Open straight-shoota opened 3 years ago

straight-shoota commented 3 years ago

The methods p/pp and macros p!/pp! are very similar with the difference being that the macros (with exclamation mark) print the expression and the result while the methods (without exclamation mark) print only the result. Supposedly, all four callables should share the same interface. There is however a difference: The methods (p/pp) accept keyword arguments (interpreted as a named tuple), while the macros (p!/pp!) do not.

p foo: "bar"   # => {foo: "bar"}
pp foo: "bar"  # => {foo: "bar"}
p! foo: "bar"  # Error: no argument named 'foo'
pp! foo: "bar" # Error: no argument named 'foo'

For consistency, I think either all should support kwargs or none.

Adding kwargs to the macros is probably the easiest solution.

HertzDevil commented 3 years ago

There are also the same top-level macro methods:

{% p foo: "bar" %}   # prints nothing
{% pp foo: "bar" %}  # prints nothing
{% p! foo: "bar" %}  # Empty enumerable (Enumerable::EmptyError)
{% pp! foo: "bar" %} # Empty enumerable (Enumerable::EmptyError)

The stack trace is:

Empty enumerable (Enumerable::EmptyError)
  from src/enumerable.cr:976:5 in 'interpret_pp!'
  from src/compiler/crystal/macros/methods.cr:63:9 in 'interpret_top_level_call?'
  from src/compiler/crystal/macros/methods.cr:43:7 in 'interpret_top_level_call'
  from src/compiler/crystal/macros/interpreter.cr:389:9 in 'visit'
  from src/compiler/crystal/syntax/visitor.cr:27:12 in 'accept'
  from src/compiler/crystal/macros/interpreter.cr:100:7 in 'visit'
  from src/compiler/crystal/syntax/visitor.cr:27:12 in 'accept'
  from src/compiler/crystal/macros/macros.cr:29:5 in 'expand_macro'
  from src/compiler/crystal/semantic/semantic_visitor.cr:434:9 in 'expand_inline_macro'
  from src/compiler/crystal/semantic/semantic_visitor.cr:420:3 in 'expand_inline_macro'
  from src/compiler/crystal/semantic/semantic_visitor.cr:179:5 in 'visit'
  from src/compiler/crystal/syntax/visitor.cr:27:12 in 'accept'
  from src/compiler/crystal/semantic/top_level_visitor.cr:756:9 in 'visit'
  from src/compiler/crystal/syntax/visitor.cr:27:12 in 'accept'
  from src/compiler/crystal/semantic.cr:62:7 in 'top_level_semantic'
  from src/compiler/crystal/semantic.cr:22:23 in 'semantic'
  from src/compiler/crystal/compiler.cr:171:7 in 'compile'
  from src/compiler/crystal/command.cr:296:3 in 'compile'
  from src/compiler/crystal/command.cr:208:14 in 'run_command'
  from src/compiler/crystal/command.cr:117:7 in 'run'
  from src/compiler/crystal/command.cr:49:5 in 'run'
  from src/compiler/crystal/command.cr:48:3 in 'run'
  from src/compiler/crystal.cr:11:1 in '__crystal_main'
  from src/crystal/main.cr:110:5 in 'main_user_code'
  from src/crystal/main.cr:96:7 in 'main'
  from src/crystal/main.cr:119:3 in 'main'
  from __libc_start_main
  from _start
  from ???