-
Notifications
You must be signed in to change notification settings - Fork 23
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Every value should be printable with echo #203
Comments
@Araq You asked for this RFC here. Now you can complain about it here. |
Regarding distinct types: I'd suggest this RFC does not implement the stringify procedure. As the manual essentially promises that a distinct type will not implicate conversions to the base type which this RFC would violate. |
@0xACE regarding "implicit conversion". This is not an implicit conversion. This is after all an explicit conversion to string with the |
recursive expansion of ptr/ref by default is a bad idea
A hash table is the only sane way to deal with ref/ptr aliasingStatic detection of cycles (as you're using in your PR) is the wrong criterion to use, and has both false positives and false negatives in terms of what gets duplicated. Instead, the correct way is to do what a cycle-aware serializer does, for example depth first search visit of each node, marking the ones already visited to avoid duplicates, using a hash table to mark node addresses. That's precisely what I've implemented in my own pretty printer. The criterion you're using allows duplicate printing of nodes when you have a DAG, eg: see example2 I gave in nim-lang/Nim#13687 (comment), it causes duplicate printing as follows:
And on the other hand, it doesn't print nodes that should be printed (aren't duplicates), eg: block:
type Foo = ref object
id: int
next: Foo
let a = Foo(id: 10, next: Foo(id: 11))
echo a prints proposalit's impossible to satisfy every use case with builtin proposal part 1: keep
|
You are describing the problem itself. Here the The I understand that implementing this would help with a "resistance free" programming approach for |
Two thoughts to share regarding this proposal:
|
I think this argument is so strong that I cannot imagine a stronger argument that is in favor of "$ for distinct".
Yes! That's the solution we should have. Zahary's |
Please don't print Currently the best way to create a secret cryptographic keys type is to use a Assuming you somehow import the type and but don't import the i.e. if you allow printing |
It is not a great guarantee, after all. If you have access to an instance of a key, you can take its address and read the raw memory. Moreover, you are trying to protect against an attacker who is... writing the application? |
It's to protect against misuse. Most of the cryptographic problems currently are due to misuse of libraries API, and anything that help against such misuse is a win see https://www.usenix.org/legacy/publications/library/proceedings/sec02/full_papers/gutmann/gutmann_html/index.html |
|
|
This RFC is stale because it has been open for 1095 days with no activity. Contribute a fix or comment on the issue, or it will be closed in 7 days. |
Fwiw we have packages for this, like https://github.com/treeform/pretty |
In my own experience
echo
is used most heavily for debugging purposes. It is part of the hello world program, and then it is continuously used to explore the programming language and long the behavior of the program. It is also used to put values into error messages, for example inraise newException(KeyError, "key not found: " & $key
). But some types are just not printable with$
. This usually comes as a surprise, especially in generic code, as the majority of types do already have a$
overload.The solution to the problem is to provide a generic solution of
$
for every type that the Nim language allows, so thatecho x
and"key not found: " & $key
will always compile, no matter what the value is.After all these overloads would be need an addition:
ref
/ptr
typesref
types are the natuarl thing to use in Nim, when the code is inteded to be executed on a javascript vm, as this is what the backend naturally supports and doesn't need to be emulated. But the big disadvantage of using aref
type is that it isn't printable withecho
. My suggestion is to provide the following implementation:This implementation is able to print
nil
when required, but otherwise the output won't make it obvious that it prints a pointer value. Sometimes people care about the pointer values and they want to see them. But pointer values are at least 16 characters in hex and therefore very verbose in the output. To my experience people usually really don't care about the pointer value. As long as it points to something valid, it should print just that, not some hexadecimal string.Dealing with Cycles
The current implementation of
$
on objects iterates all printable fields recursively. This is problematic, as with this RFC it will run into infinite recursion if the value forms a pointer circle. An because$
is located insystem.nim
and no further imports are allowed, a hash map to store previously visited nodes can't be used.However there is already a nice static analyser built into the compiler to detect if a type is even able to form cycles:
canFormAcycle
. Pointers to such recursive types could then be printed as just...
like non printable types are represented right now. This isn't very helpful, but still much more helpful that printing allptr
/ref
types as "...".Distinct Types
It is easy to implement
$
for distinct types:The question though remains, should distinctness simply be shaved off here? After all the programmer explicitly asked for a new incompatible type. @Araq mentioned this could be dangerous because of SQL injection. But I don't think this is really a problem. After all a distinct string remains a distinct string and it is not automatically converted to
string
. It is only converted inecho
because it explicitly attaches a$
conversion to every argument. Maybe a distinct string should be quoted and not just printed. Or it should be altered in some other way. But that is still open to discussion. But I do think something should be printed.Pointer
The type
pointer
doesn't have any content it can print. The only thing that it can print is the value of the pointer itself. Earlier I argued printing actual pointer values is verbose, but here there is nothing else that can be printed. So it should be done. After all fields that are of typepointer
are rare.Callbacks
Unfortunately I don't have a good solution for
proc
value. I can check if they are nil and print "nil" if they are nil. But unfortunately I cannot print anything useful in the other case. Acdecl
callback can be cast to apointer
and the address can be printed. But that doesn't work for closures.gdb
can print even the name of a cdecl callback, but I don't know how to do that in Nim.I have a PR where this RFC has been implemented. It also shows how code would be simplified in the standard library and the compiler when after all a
$
is available for everything.The text was updated successfully, but these errors were encountered: