Open ningan123 opened 2 years ago
As CUE is by design a hermetic language, this isn't something that can be incorporated directly.
If you just want a known number of random numbers, there is an option to inject 128-bit random numbers into the CUE (see cue help injection
). For example:
#aRandomNumber: int @tag(seed,var=rand)
You'll have to evaluate with the -T
command line flag for this to work though.
It is just about technically possible to use that single random number to generate an arbitrary set of other random numbers, but I wouldn't recommend doing so. It might be that a new addition to the standard library could make that easier, but that depends somewhat on your use case. With that in mind, what are you actually trying to do? i.e. what's your use case for generating random numbers?
Maybe something like tool/rand
would be acceptable?
As CUE is by design a hermetic language, this isn't something that can be incorporated directly.
If you just want a known number of random numbers, there is an option to inject 128-bit random numbers into the CUE (see
cue help injection
). For example:#aRandomNumber: int @tag(seed,var=rand)
You'll have to evaluate with the
-T
command line flag for this to work though.It is just about technically possible to use that single random number to generate an arbitrary set of other random numbers, but I wouldn't recommend doing so. It might be that a new addition to the standard library could make that easier, but that depends somewhat on your use case. With that in mind, what are you actually trying to do? i.e. what's your use case for generating random numbers?
Actually, with the random number mentioned above, 1) I want a 32bit string, the format is [0-9a-z]{32}. So, I want a random number to select a character randomly between [0-9a-z] for 32 times. 2) I want to choose a number in [A, B] randomly. eg.[100, 200]
As CUE is by design a hermetic language, this isn't something that can be incorporated directly.
If you just want a known number of random numbers, there is an option to inject 128-bit random numbers into the CUE (see
cue help injection
). For example:#aRandomNumber: int @tag(seed,var=rand)
You'll have to evaluate with the
-T
command line flag for this to work though.It is just about technically possible to use that single random number to generate an arbitrary set of other random numbers, but I wouldn't recommend doing so. It might be that a new addition to the standard library could make that easier, but that depends somewhat on your use case. With that in mind, what are you actually trying to do? i.e. what's your use case for generating random numbers?
With your suggestion, I have generated a 128bit random number successfully. Now, I wanna change it to the string format. However, the following function is int64, the generated number is int128. It doesn't match. How can I do it? Thank u.
func FormatInt(i int64, base int) string
Maybe something like
tool/rand
would be acceptable?
Actually, with the random number mentioned above, 1) I want a 32bit string, the format is [0-9a-z]{32}. So, I want a random number to select a character randomly between [0-9a-z] for 32 times. 2) I want to choose a number in [A, B] randomly. eg.[100, 200]
My go project needs to import the cue package, like this:
// test.go
import (
"fmt"
"cuelang.org/go/cue/ast"
"cuelang.org/go/cue/load"
"cuelang.org/go/cue/cuecontext"
)
func main(){
ctx := cuecontext.New()
entryPoints := []string{"test.cue"}
b := ctx.BuildInstance(...)
...
fmt.Printf("b: %s\n", b)
}
// test.cue
// I'm not familiar with cue, so I write my thought in go.
str := "0123456789abcdefghijklmnopqrstuvwxyz"
var token string
for i := 0; i < 32; i++ {
rand:= rand.Intn(32) // 0-32
token += str[rand]
}
When I run
go run test.go
I expect to see
token: "781292db7bc3a58fc5f07e" // 32bit just an example
Question: 1) Does the cue support the rand function? a random number is enough. 2) Does the syntax of the cue support the thought I write in the test.cue?
Thank u so much!
A few thoughts
cue/flow
| cue cmd
| "the scripting layer") is for, though it does not have a tool/rand
function.+=
. You could comprehend a list of chars and then strings.Join
that into a single string.One option is to generate the random value from Go and Fill it into a Value. This means you will have to write a Go program and use CUE's GoAPI.
@mvdan and I discussed, and we'll try to bring together the various threads in this issue.
Firstly, on the question of "how do I get random values in CUE?", the answer depends on the context and what you're trying to solve:
cmd/cue
with the -T
flag, as pointed out by @rogpeppe in https://github.com/cue-lang/cue/issues/1646#issuecomment-1104104746Here is an example that shows all three in action:
exec go mod tidy
# cue eval example. Note we need to
# explicitly provide -T for cue eval.
# This ensures that cue eval is hermetic
# by default (same applies for def, export
# and vet).
exec cue eval -T -e u2
# cue cmd example. Note that -T
# is enabled by default for cue cmd. This
# is because cue cmd is by definition not
# hermetic, i.e. the tasks can have arbitrary
# side effect etc.
exec cue cmd print
# go API example
exec go run main.go
-- go.mod --
module mod.com
go 1.18
require cuelang.org/go v0.4.3
-- main.go --
package main
import (
"fmt"
"cuelang.org/go/cue"
"cuelang.org/go/cue/cuecontext"
"cuelang.org/go/cue/load"
)
func main() {
ctx := cuecontext.New()
opts := &load.Config{
TagVars: load.DefaultTagVars(),
}
bps := load.Instances([]string{"."}, opts)
vs, err := ctx.BuildInstances(bps)
if err != nil {
panic(err)
}
u2 := vs[0].LookupPath(cue.MakePath(cue.Str("u2")))
fmt.Printf("u2: %v\n", u2)
}
-- x.cue --
package x
import "uuid"
import "strings"
x: int @tag(x, var=rand)
u: uuid.FromInt(x)
u2: strings.Replace(u, "-", "", -1)
-- x_tool.cue --
package x
import "tool/cli"
command: print: cli.Print & {
text: "u2: \(u2)"
}
Each of the three examples uses the CUE in x.cue
.
The first case of normal CUE evaluation uses injection to introduce a random value into evaluation. Because CUE evaluation is designed to be hermetic, the -T
flag is explicitly required here to signal that as the caller you know you are injecting (random) values that might influence the evaluation result.
The second example using the tooling layer simply wraps that same CUE with a command specification in x_tool.cue
. Note that in this case the -T
flag is not required. Because the tooling layer by design allows you to evaluate code that has side effects, introduces random values etc. We again use the rand
tag var, but we could equally use the result of a task as the source of randomness.
The third example of the Go API usage simply shows how to do the equivalent of the first case but via the Go API. It also hints at how you could specify a different random value by using a source other than load.DefaultTagVars()
.
I think from looking at your examples you're tending towards the third case?
The one thing I will flag is that looking at your responses, it appears you might be better using the uuid
tag var instead of rand
. Because then as you can see from x.cue
, you could simply avoid the step of creating a UUID yourself. However, for creating a sequence of UUIDs a sequence of random numbers is likely a better starting point.
That said, I think the missing functionality here is the ability, as @rogpeppe highlighted, to create a pseudo-random number from a seed. We don't have anything like math.Rand()
right now, which means that you need to resort to some of the gymnastics that @rogpeppe highlighted in https://github.com/cue-lang/cue/issues/1646#issuecomment-1104104746.
So in conclusion, I think this issue does have merit as a feature request for such pseudo random number builtin, one that works with *big.Int
so as to be compatible with the rand
tag var. This would allow you to create a sequence of random numbers using a cryptographically random seed, or a sequence of UUIDs for that matter.
On that basis I'll re-open this issue.
Please shout if I've missed anything here.
Building on my last comment, I'm not totally clear that we strictly need the ability to generate a sequence of random numbers; generating a single pseudo random number will suffice because creating a sequence/map of random numbers is relatively straightforward when required:
package x
import "list"
_x: int @tag(x, var=rand)
l: [ for i in list.Range(0, 3, 1) {(*(l[i-1] ) | _x) / 2}]
_ks: ["m1", "m2", "m3"]
m: {
for i, k in _ks {
(k): (*(m[_ks[i-1]] ) | _x ) / 2
}
}
In the example above I've substituted / 2
in place of a call to math.Rand()
or whatever solution we come up with here. Hopefully the idea is clear though in terms of generating "the next number in the sequence".
That said, if a sequence-like function proves useful we could clearly add that too.
Is your feature request related to a problem? Please describe.
I wanna generate a random number in .cue file. However, I can't find a function to do it.
Describe the solution you'd like
I want a function that can generate a random number in .cue file.
test.cue
run
cue export test.cue
Then the output is
I just want a function that can generate a random number, the function name is not important.
Thank u!
Describe alternatives you've considered
Additional context