-
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
const should work with ref types #271
Comments
One downside that I can see is this RFC is in direct contrast to #257 (which was accepted). |
If you handle |
that's not the same at all. The point is this feature allows caching the result of a potentially expensive computation or something that should be computed just once for correctness. with nim-lang/Nim#15528 this works: import std/json
proc fn(file: static string): JsonNode =
echo "parsing " & file
const s = staticRead(file)
result = parseJson(s)
const j = fn("/tmp/myconfig.json") # fn will be called just once
proc main() =
# CT code can now use `j`, eg:
const version = j["version"].getStr
const name = j["name"].getStr
# RT code can also use `j`, eg:
echo (version, name)
echo j.pretty.static
echo j["name"].getStr.static
echo j["version"].getStr.static
main() I don't see how I'm using this to great effect in my own patched nim. |
And how do you "cache" it? Previously you claimed it doesn't affect GC safety. |
no contradiction; it's cached in the same way it's cached for non-ref types, after Subsequent const accesses (eg example 1 (from example above)echo j["name"].getStr.static
# is same as:
const tmp: string = j["name"].getStr
echo tmp # the `tmp` string gets pasted where it's used, as if the code was: echo "foobar" example 2 (more complex example):when true:
type Foo = ref object
n: int
lhs, rhs: Foo
proc fn(n: int): Foo =
result = Foo(n: n)
if n > 1:
if n mod 2 == 0:
result.lhs = fn(n div 2)
if n mod 2 == 1:
result.rhs = fn((n+1) div 2)
const j1 = fn(20)
let j2 = j1
# same as if we inlined the following
# let j2 = Foo(n: 20, lhs: Foo(n: 10, lhs: Foo(n: 5, rhs: Foo(n: 3, rhs: Foo(n: 2, lhs: Foo(n: 1))))))
# `fn` is not re-evaluated here
|
Thanks. It's growing on me... |
Maybe I'm missing something, but isn't the point of |
type Foo = ref object
x1: int # etc; can contain other nested ref types
proc foo(n: int): Foo =
# potentially expensive computation (potentially non-pure or with CT side effects)
const a1 = foo(3) # a is not codegen'd but computed at CT; foo(3) is computed just here
const a2 = a1.x1 # foo() is not recomputed here
let a3 = a2 # only a2 is codegen'd here; or, more directly, `let a3 = a1.x1.static`
const a4 = foo(4) # foo(4) computed just here
let a5 = a4 # a5 is codegen'd, using a literal, eg as if `let a5 = Foo(x1: ...)` was written This simply extends const to work at CT, it otherwise works the same as types that don't contain (nested) ref |
fully implemented in PR nim-lang/Nim#15528, see PR for details, tests, examples, and discussion.
(RFC was requested here: nim-lang/Nim#15528 (comment))
highlights under this PR:
const a = expr
now works even if expr (recursively) contains some ref type, instead of giving CT errora
isn't codegen'd, but its value is pasted in each context where it's used at RT, consistent with current behavior with non-ref typesimport tables; const a = {1: "1", 2: "2"}.newTable
now worksprecedent in other languages
enum
(manifest constant, not codegen'd but pasted in each runtime context where it's used) andstatic const
(codegen'd in ROM memory, not pasted). This PR makes nim'sconst
work the same as D's enum (which also works with ref types)The text was updated successfully, but these errors were encountered: