--
You received this message because you are subscribed to the Google Groups "elixir-lang-core" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elixir-lang-co...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
--
You received this message because you are subscribed to the Google Groups "elixir-lang-core" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elixir-lang-co...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
On Sat, Apr 5, 2014 at 6:30 PM, Eric Meadows-Jönsson <eric.meado...@gmail.com> wrote:
iex always inspects the result, it never calls `to_string`. `inspect` should really, only be used during development or when debugging. If you have `inspect` in production code it is likely you are doing something wrong. With this mind do we really need a special syntax for `"#{inspect expr}"`?The falling back behaviour seems worse. If `"#{...}"` was confusing before, this will definitely make it more confusing.
I always find it interesting just how differently we approach coding. I’d much rather make things convenient for other developers, rather than come up with perfectly good reasons why they aren’t.
I don’t necessarily want inspect output being sent to customers, but it really is quite convenient in logs, and while developing. When I write
IO.puts "the result is #{answer}"
to a log, I would like to see output regardless of the type of result. The alternative is either always to use inspect or to put up with exceptions.
However, I can see the other argument—that you’d rather raise an exception than have the value {1,2,3} leak into some string interpolation.
On balance, I find it more useful for interpolation to always give a result.
Dave
--
You received this message because you are subscribed to the Google Groups "elixir-lang-core" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elixir-lang-co...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
I think it is better to error than to try and guess
…
So you’ll be removing this behavio(u)r in the next release?
a = 1230000.0
IO.puts "value is #{a}"
"value is 1.23e6"
and, logically, you definitely need to remove this, too:
b = "\024"
IO.puts "value is #{b}"
"value is ^T"
And, of course, there’s always this one:
c = Enum.map ~w{ I am sad }, &String.length/1
IO.puts "The lengths are #{c}"
The lengths are ^A^B^C
In all these cases you are choosing a representation for a value where the value is not originally a string. to_string has to guess on a way of converting that value into a human-readable representation. And that representation “leaks” into a string.
I see no difference between that and
d = {1,2,3}
IO.puts "value is #{d}"
IO.puts “Signed: #{[4, 1, 22, 5]}”
After thinking more about this, I'm going to solve this for myself with a new sigil. I now appreciate this is a discussion around intent. My intent is to inspect so creating a new 'inspect' sigil make my code more explicit and solves the problem.
I didn't think this through. A sigil doesn't really help since I would need to wrap it with interpolation syntax:
IO.puts "the result is #{~I(answer)}"IO.puts "the result = #{:ok}" the result = ok
a = Array.new [1,2,3] puts "Array = #{a}" Array = [1, 2, 3] a = {one: 5, two: 3} puts "a = #{a}" a = {:one=>5, :two=>3} class Steve end steve = Steve.new puts "steve = #{steve}" steve = #<Steve:0x007fe225839528>
Could you give some example code on how you are using inspect? There is probably a better way than #{inspect(term)}.
cond do
dsp_unit == 0 ->
Mdse.error "DsetSm.close_audio_stream #{h2s cx.unit} invalid dsp_unit: #{inspect dsp_unit}"
far_end_port <= 0 ->
Mdse.error "DsetSm.close_audio_stream #{h2s cx.unit} invalid far_end_port: #{far_end_port}"
far_end_ip == [] ->
Mdse.error "DsetSm.close_audio_stream #{h2s cx.unit} invalid dsp_unit: #{inspect far_end_ip}"
true ->
if media_path(cx, dsp_unit, channel, channel + 2, far_end_ip, far_end_port, :clear) != :ok do
Mdse.error "dsetsm.close_audio_stream #{h2s cx.unit} could not idle media path"
end
Mdse.ResourceManager.idle_unit!(dsp_unit)
end
When you say logging for tracing, perhaps you want to use the builtin support for tracing (several erlang trace utilities available on BEAM) rather than littering code with debug printing when developing. There is also the :sys module that can log messages (both in and out) or retrieve the state of a process when using an OTP behaviour.
I looked at number of different logging solutions before I decided to roll my own. I would love to find a better solution than littering my code with all these log statements. To understand my requirements, I should explain the application.
- My application sits between two legacy phone systems and basically acts a protocol converter.
- On one side, I talk over a reliable UDP protocol, establishing a connection for 1 to 1000 registered phones
- On the other side, I manage 1..n servers with 4 different TCP links and a reliable UDP connection
- I have 3 different :gen_fsm and about 10 :gen_servers
My logging requirements based on a similar solution that I'm replacing:
- An administrator console where they can print status information about various resources, issue commands to enable and disable various things, as well as change run time log levels
- Enable / disable individual component log levels
- Write logs to a file that is managed with log rotate
- Write logs in a specific format that can be reformatted by existing external program
I would love to find a solution that allows developer debugging and administrator access run time log level control that does not plaster my code with log statements and does not crash sometime in the future because I missed an inspect in some obscure case that happens only on a blue moon.Steve
I think it is better to error than to try and guess…So you’ll be removing this behavio(u)r in the next release?
a = 1230000.0 IO.puts "value is #{a}" "value is 1.23e6"and, logically, you definitely need to remove this, too:
b = "\024" IO.puts "value is #{b}" "value is ^T"And, of course, there’s always this one:
c = Enum.map ~w{ I am sad }, &String.length/1 IO.puts "The lengths are #{c}" The lengths are ^A^B^CIn all these cases you are choosing a representation for a value where the value is not originally a string.
to_stringhas to guess on a way of converting that value into a human-readable representation. And that representation “leaks” into a string.
Here is another inconstancy:IO.puts "the result = #{:ok}" the result = ok
cond do dsp_unit == 0 -> Mdse.error "DsetSm.close_audio_stream #{h2s cx.unit} invalid dsp_unit: #{inspect dsp_unit}" far_end_port <= 0 -> Mdse.error "DsetSm.close_audio_stream #{h2s cx.unit} invalid far_end_port: #{far_end_port}" far_end_ip == [] -> Mdse.error "DsetSm.close_audio_stream #{h2s cx.unit} invalid dsp_unit: #{inspect far_end_ip}" true -> if media_path(cx, dsp_unit, channel, channel + 2, far_end_ip, far_end_port, :clear) != :ok do Mdse.error "dsetsm.close_audio_stream #{h2s cx.unit} could not idle media path" end Mdse.ResourceManager.idle_unit!(dsp_unit) end
I looked at number of different logging solutions before I decided to roll my own. I would love to find a better solution than littering my code with all these log statements. To understand my requirements, I should explain the application.
Dave, that's not what is happening with 2 of your 3 examples. When you see "value is ^T", you are seeing the inspected value. to_string for binaries is receiving bytes and outputting bytes. to_string for char lists are treating them as chars. There is no other option for to_string(<<0, 10, 11>>) to return than <<0, 10, 11>>. The fact you see ^T is actually a decision made by inspect, not by to_string nor interpolation.
Umm, no.
What we’re talking about is the way #{…} works. You’re talking about implementation, but the real question comes from the developer’s side.
People argued that "value: #{ {1,2,3} }" should result in "value: {1,2,3}". Others said “No, because that’s inspect behavio(u)r.
But my point is that we already do something similar with lists and non-printing values. Whether that is implemented using inspect inside to_string or by emailing the elves and asking what they’d do, the result (as far as the developer is concerned) is the same—string interpolation is not and has never been pure—the concept of to_string already involves some interpretation (read “guessing”) on the part of the runtime.
So why not just accept that and extend it further. Doing so would be a great convenience to users of the language.
Dave
Umm, no.
What we’re talking about is the way #{…} works. You’re talking about implementation, but the real question comes from the developer’s side.
the concept of to_string already involves some interpretation (read “guessing”) on the part of the runtime.
You bring up a good point Dave.
Maybe we should error when running to_string on binaries and lists that are not printable. On the other hand, those are the only two types we do that for. They are also the only two types in elixir that are strings, so maybe we should make an exception for actual string types.
--
You received this message because you are subscribed to the Google Groups "elixir-lang-core" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elixir-lang-co...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
This is a wild guess and I don't have a complete idea of the application requirements. But what if far_end_ip was a record/struct? If you implement it as so, you can implement the String.Chars protocol for such structure and get a fair representation of it that makes sense to your application.
So if the main goal is logging, I would rather find ways to make it better for logging. Maybe providing a %i"this will be inspected: #{val}".