I was parsing some string input from a file when I came across this error. Normally it should not make a difference if you chain a series of methods on a single line or separate them into multiple operations. Yet here, it does not compile when the method chain is in a single line.
I do not get an error when split to multiple statements like so (link to playground)
let input = std::fs::read_to_string("tst_input.txt").expect("Failed to read input");
let input = input
.lines()
.map(|l| {
let mut iter = l.split(" | ");
(
iter.next()
.unwrap()
.split_whitespace()
.collect::<Vec<&str>>(),
iter.next()
.unwrap()
.split_whitespace()
.collect::<Vec<&str>>(),
)
})
.collect::<Vec<_>>();
I get a lifetime error when it is in a single statement like so (link to playground)
let input = std::fs::read_to_string("tst_input.txt")
.expect("Failed to read input")
.lines()
.map(|l| {
let mut iter = l.split(" | ");
(
iter.next()
.unwrap()
.split_whitespace()
.collect::<Vec<&str>>(),
iter.next()
.unwrap()
.split_whitespace()
.collect::<Vec<&str>>(),
)
})
.collect::<Vec<_>>()
error[E0716]: temporary value dropped while borrowed
--> src/main.rs:2:17
|
2 | let input = std::fs::read_to_string("tst_input.txt")
| _________________^
3 | | .expect("Failed to read input")
| |_______________________________________^ creates a temporary which is freed while still in use
...
18 | .collect::<Vec<_>>();
| - temporary value is freed at the end of this statement
19 | println!("{:?}", input);
| ----- borrow later used here
|
= note: consider using a `let` binding to create a longer lived value
Should these 2 cases be effectively identical? why is the compiler treating them differently? Could this possibly be a compiler error?
These two cases are not identical, since the stored information differs.
In Rust, variables have semantic meaning: they act as a place where the information is stored, and, what's more important, they define when this information is destroyed - this is handled by Drop trait. By default, drop method is called for every variable which goes out of scope; this can be overridden with mem::forget and some other functions like Box::into_raw, but these are rather niche cases.
In the first case, the data being read is stored into the input variable of type String. This type wraps Vec<u8>, which implements Drop, so this data is deallocated when input goes out of scope. Then, the second input variable is of type Vec<(Vec<&str>, Vec<&str>)> - you can see that it contains a reference, so it is borrowing from the first input, so it must live no longer then the source string. Here, this is satisfied - of course, as long as you don't try to return this value up the stack, in which case the source string is dropped, and the references would dangle.
In the one-line version, however, the string is not stored anywhere - it is a temporary, which is destroyed right at the end of statement. That's why you're not allowed to hold any references to it. You can, however, make an owned version of the split data, by inserting an extra mapping operation:
let _: Vec<(Vec<String>, Vec<String>)> = std::fs::read_to_string("tst_input.txt")
.expect("Failed to read input")
// This iterator borrows from the temporary...
.lines()
.map(|l| {
// ...this iterator reborrows that borrow...
let mut iter = l.split(" | ");
(
iter.next()
.unwrap()
.split_whitespace()
// ...and this operation clones the source data,
// so they are copied to the new owned location,
// and not referenced anymore, so can be freely dropped
.map(str::to_owned)
.collect::<Vec<_>>(),
iter.next()
.unwrap()
.split_whitespace()
.map(str::to_owned)
.collect::<Vec<_>>(),
)
})
.collect::<Vec<_>>();
A minimal recreation of the issue might help
let split_value = String::from("example")// <- string owned value
.split("x");
// string has no owner, so its lifetime ends
println!("{:?}", split_value); //error
A reference must not outlive the lifetime of the value it is referencing. Because the string is not being stored anywhere, and therefore has no owner, the value's lifetime ends.
And because split returns data that references that string value, its lifetime is linked to that string so it also ends.
By storing the result in a variable, the string now has a lifetime that lives past the expression.
let str_result = String::from("example"); //str_result owns the string value
let split_value = s.split("x");
println!("{:?}", r);
split_value can be printed because str_result's lifetime ends at the end of the function, therefore references to str_result are valid too.
Related
i have extracted the fix message as below from Unix server and now need to convert this message into JSON. how can we do this?
8=FIXT.1.1|9=449|11=ABCD1|35=AE|34=1734|49=REPOFIXUAT|52=20140402-11:38:34|56=TR_UAT_VENDOR|1128=8|15=GBP|31=1.7666|32=50000000.00|55=GBP/USD|60=20140402-11:07:33|63=B|64=20140415|65=OR|75=20140402|150=F|167=FOR|194=1.7654|195=0.0012|460=4|571=7852455|1003=2 USD|1056=88330000.00|1057=N|552=1|54=2|37=20140402-12:36:48|11=NOREF|453=4|448=ZERO|447=D|452=3|448=MBY2|447=D|452=1|448=LMEB|447=D|452=16|448=DOR|447=D|452=11|826=0|78=1|79=default|80=50000000.00|5967=88330000.00|10=111
Note: I tried to make this a comment on the answer provided by #selbie, but the text was too long for a comment, so I am making it an answer.
#selbie's answer will work most of the time, but there are two edge cases in which it could fail.
First, in a tag=value field where the value is of type STRING, it is legal for value to contain the = character. To correctly cope with this possibility, the Java statement:
pair = item.split("=");
should be changed to:
pair = item.split("=", 2);
The second edge case is when there are a pair of fields, the first of which is of type LENGTH and the second is of type DATA. In this case, the value of the LENGTH fields specifies the length of the DATA field (without the delimiter), and it is legal for the value of the DATA field to contain the delimiter character (ASCII character 1, but denoted as | in both the question and Selbie's answer). Selbie's code cannot be modified in a trivial manner to deal with this edge case. Instead, you will need a more complex algorithm that consults a FIX data dictionary to determine the type of each field.
Since you didn't tag your question for any particular programming language, I'll give you a few sample solutions:
In javascript:
let s = "8=FIXT.1.1|9=449|11=ABCD1|35=AE|34=1734|49=REPOFIXUAT|52=20140402-11:38:34|56=TR_UAT_VENDOR|1128=8|15=GBP|31=1.7666|32=50000000.00|55=GBP/USD|60=20140402-11:07:33|63=B|64=20140415|65=OR|75=20140402|150=F|167=FOR|194=1.7654|195=0.0012|460=4|571=7852455|1003=2 USD|1056=88330000.00|1057=N|552=1|54=2|37=20140402-12:36:48|11=NOREF|453=4|448=ZERO|447=D|452=3|448=MBY2|447=D|452=1|448=LMEB|447=D|452=16|448=DOR|447=D|452=11|826=0|78=1|79=default|80=50000000.00|5967=88330000.00|10=111"
let obj = {};
items = s.split("|")
items.forEach(item=>{
let pair = item.split("=");
obj[pair[0]] = pair[1];
});
let jsonString = JSON.stringify(obj);
Python:
import json
s = "8=FIXT.1.1|9=449|11=ABCD1|35=AE|34=1734|49=REPOFIXUAT|52=20140402-11:38:34|56=TR_UAT_VENDOR|1128=8|15=GBP|31=1.7666|32=50000000.00|55=GBP/USD|60=20140402-11:07:33|63=B|64=20140415|65=OR|75=20140402|150=F|167=FOR|194=1.7654|195=0.0012|460=4|571=7852455|1003=2 USD|1056=88330000.00|1057=N|552=1|54=2|37=20140402-12:36:48|11=NOREF|453=4|448=ZERO|447=D|452=3|448=MBY2|447=D|452=1|448=LMEB|447=D|452=16|448=DOR|447=D|452=11|826=0|78=1|79=default|80=50000000.00|5967=88330000.00|10=111"
obj = {}
for item in s.split("|"):
pair = item.split("=")
obj[pair[0]] = pair[1]
jsonString = json.dumps(obj)
Porting the above solutions to other languages is an exercise for yourself. There's comments below about semantic ordering and handling cases where the the = or | chars are part of the content. That's on you to explore if you need to support those scenarios.
Ok here goes...
I have been experimenting on various examples of declaring functions with "self" in the parameters.
I don't have full understanding of this which is what I'm trying to fully understand. I'm a complete beginner, but I am compelled to grasp this fully.
The 2 examples below return the same results, although in example 2, if I don't declare "self = {}" within the function, I need to place "self" (or the ":") in the function parameters for it to work. Is this the whole deal with "self"?
Are there other implications when using "self"?
Example 1
function Character.new(x)
self = {}
self.name = x
return self.name
end
a = Character
b = Character
hobbit = a.new ("Frodo")
dragon = b.new ("Smaug")
print (hobbit)
print (dragon)
Example 2
Character = {}
function Character:new(x)
self.name = x
return self.name
end
a = Character
b = Character
hobbit = a:new ("Frodo")
dragon = b:new ("Smaug")
print (hobbit)
print (dragon)
;^)
Zalokin
You're using global variables when you should be creating instances.
Try these lines instead, they may help you understand:
-- example 1
print (hobbit)
print(self.name)
print (dragon)
print(self.name)
and
-- example 2
print (hobbit)
print(Character.name)
print (dragon)
print(Character.name)
: lets you access the table which includes the function from within the function without an explicit (first argument) pass. It can be used both when defining and calling a function.
The example below contains a table t. The table has 3 functions (a,b and c) and a string entry under the key greeting.
All the function/method calls print the same string "hello user".
Notice how you can still call a method (a function which has its container table as the first argument) the same way as a normal function, but you have to explicitly pass the table as the first argument.
The self argument can be called what ever you want and you can still call the function with a : as long as you use the correct argument name inside the function (not self in this case). The function c serves as an example of that.
It is basically just syntax sugar.
local t = {}
t.greeting = "hello"
function t:a(name)
print(self.greeting, name)
end
function t.b(self, name)
print(self.greeting, name)
end
function t.c(myself, name)
print(myself.greeting, name)
end
t.a(t, "user")
t:a("user")
t.b(t, "user")
t:b("user")
t.c(t, "user")
t:c("user")
Is there any way to initialize a Sequential value not in one fellow swoop?
Like, can I declare it, then use a for loop to populate it, step by step?
As this could all happen inside a class body, the true immutability of the Sequential value could then kick in once the class instance construction phase has been completed.
Example:
Sequential<String> strSeq;
for (i in span(0,10)) {
strSeq[i] = "hello";
}
This code doesn't work, as I get this error:
Error:(12, 9) ceylon: illegal receiving type for index expression:
'Sequential' is not a subtype of 'KeyedCorrespondenceMutator' or
'IndexedCorrespondenceMutator'
So what I can conclude is that sequences must be assigned in one statement, right?
Yes, several language guarantees hinge on the immutability of sequential objects, so that immutability must be guaranteed by the language – it can’t just trust you that you won’t mutate it after the initialization is done :)
Typically, what you do in this situation is construct some sort of collection (e. g. an ArrayList from ceylon.collection), mutate it however you want, and then take its .sequence() when you’re done.
Your specific case can also be written as a comprehension in a sequential literal:
String[] strSeq = [for (i in 0..10) "hello"];
The square brackets used to create a sequence literal accept not only a comma-separated list of values, but also a for-comprehension:
String[] strSeq = [for (i in 0..10) "hello"];
You can also do both at the same time, as long as the for-comprehension comes last:
String[] strSeq = ["hello", "hello", for (i in 0..8) "hello"];
In this specific case, you could also do this:
String[] strSeq = ["hello"].repeat(11);
You can also get a sequence of sequences via nesting:
String[][] strSeqSeq = [for (i in 0..2) [for (j in 0..2) "hello"]];
And you can do the cartesian product (notice that the nested for-comprehension here isn't in square brackets):
[Integer, Character][] pairs = [for (i in 0..2) for (j in "abc") [i, j]];
Foo[] is an abbreviation for Sequential<Foo>, and x..y translates to span(x, y).
If you know upfront the size of the sequence you want to create, then a very efficient way is to use an Array:
value array = Array.ofSize(11, "");
for (i in 0:11) {
array[i] = "hello";
}
String[] strSeq = array.sequence();
On the other hand, if you don't know the size upfront, then, as described by Lucas, you need to use either:
a comprehension, or
some sort of growable array, like ArrayList.
I was wondering why this is valid go code:
func FindUserInfo(id string) (Info, bool) {
it, present := all[id]
return it, present
}
but this isn't
func FindUserInfo(id string) (Info, bool) {
return all[id]
}
is there a way to avoid the temporary variables?
To elaborate on my comment, the Effective Go mentions that the multi-value assignment from accessing a map key is called the "comma ok" pattern.
Sometimes you need to distinguish a missing entry from a zero value. Is there an entry for "UTC" or is that the empty string because it's not in the map at all? You can discriminate with a form of multiple assignment.
var seconds int
var ok bool
seconds, ok = timeZone[tz]
For obvious reasons this is called the “comma ok” idiom. In this example, if tz is present, seconds will be set appropriately and ok will be true; if not, seconds will be set to zero and ok will be false.
Playground demonstrating this
We can see that this differs from calling a regular function where the compiler would tell you that something is wrong:
package main
import "fmt"
func multiValueReturn() (int, int) {
return 0, 0
}
func main() {
fmt.Println(multiValueReturn)
asgn1, _ := multiValueReturn()
asgn2 := multiValueReturn()
}
On the playground this will output
# command-line-arguments
/tmp/sandbox592492597/main.go:14: multiple-value multiValueReturn() in single-value context
This gives us a hint that it may be something the compiler is doing. Searching the source code for "commaOk" gives us a few places to look, including types.unpack
At the time of writing this it this the method's godoc reads:
// unpack takes a getter get and a number of operands n. If n == 1, unpack
// calls the incoming getter for the first operand. If that operand is
// invalid, unpack returns (nil, 0, false). Otherwise, if that operand is a
// function call, or a comma-ok expression and allowCommaOk is set, the result
// is a new getter and operand count providing access to the function results,
// or comma-ok values, respectively. The third result value reports if it
// is indeed the comma-ok case. In all other cases, the incoming getter and
// operand count are returned unchanged, and the third result value is false.
//
// In other words, if there's exactly one operand that - after type-checking
// by calling get - stands for multiple operands, the resulting getter provides
// access to those operands instead.
//
// If the returned getter is called at most once for a given operand index i
// (including i == 0), that operand is guaranteed to cause only one call of
// the incoming getter with that i.
//
The key bits of this being that this method appears to determine whether or not something is actually a "comma ok" case.
Digging into that method tells us that it will check to see if the mode of the operands is indexing a map or if the mode is set to commaok (where this is defined does give us many hints on when it's used, but searching the source for assignments to commaok we can see it's used when getting a value from a channel and type assertions). Remember the bolded bit for later!
if x0.mode == mapindex || x0.mode == commaok {
// comma-ok value
if allowCommaOk {
a := [2]Type{x0.typ, Typ[UntypedBool]}
return func(x *operand, i int) {
x.mode = value
x.expr = x0.expr
x.typ = a[i]
}, 2, true
}
x0.mode = value
}
allowCommaOk is a parameter to the function. Checking out where unpack is called in that file we can see that all callers pass false as an argument. Searching the rest of the repository leads us to assignments.go in the Checker.initVars() method.
l := len(lhs)
get, r, commaOk := unpack(func(x *operand, i int) { check.expr(x, rhs[i]) }, len(rhs), l == 2 && !returnPos.IsValid())
Since it seems that we can only use the "comma ok" pattern to get two return values when doing a multi-value assignment this seems like the right place to look! In the above code the length of the left hand side is checked, and when unpack is called the allowCommaOk parameter is the result of l == 2 && !returnPos.IsValid(). The !returnPos.IsValid() is somewhat confusing here as that would mean that the position has no file or line information associated with it, but we'll just ignore that.
Further down in that method we've got:
var x operand
if commaOk {
var a [2]Type
for i := range a {
get(&x, i)
a[i] = check.initVar(lhs[i], &x, returnPos.IsValid())
}
check.recordCommaOkTypes(rhs[0], a)
return
}
So what does all of this tell us?
Since the unpack method takes an allowCommaOk parameter that's hardcoded to false everywhere except in assignment.go's Checker.initVars() method, we can probably assume that you will only ever get two values when doing an assignment and have two variables on the left-hand side.
The unpack method will determine whether or not you actually do get an ok value in return by checking if you are indexing a slice, grabbing a value from a channel, or doing a type assertion
Since you can only get the ok value when doing an assignment it looks like in your specific case you will always need to use variables
You may save a couple of key strokes by using named returns:
func FindUserInfo(id string) (i Info, ok bool) {
i, ok = all[id]
return
}
But apart from that, I don't think what you want is possible.
Simply put: the reason why your second example isn't valid Go code is because the language specification says so. ;)
Indexing a map only yields a secondary value in an assignment to two variables. Return statement is not an assignment.
An index expression on a map a of type map[K]V used in an assignment or initialization of the special form
v, ok = a[x]
v, ok := a[x]
var v, ok = a[x]
yields an additional untyped boolean value. The value of ok is true if the key x is present in the map, and false otherwise.
Furthermore, indexing a map is not a "single call to a multi-valued function", which is one of the three ways to return values from a function (the second one, the other two not being relevant here):
There are three ways to return values from a function with a result type:
The return value or values may be explicitly listed in the "return" statement. Each expression must be single-valued and assignable to the corresponding element of the function's result type.
The expression list in the "return" statement may be a single call to a multi-valued function. The effect is as if each value returned from that function were assigned to a temporary variable with the type of the respective value, followed by a "return" statement listing these variables, at which point the rules of the previous case apply.
The expression list may be empty if the function's result type specifies names for its result parameters. The result parameters act as ordinary local variables and the function may assign values to them as necessary. The "return" statement returns the values of these variables.
As for your actual question: the only way to avoid temporary variables would be using non-temporary variables, but usually that would be quite unwise - and probably not much of an optimization even when safe.
So, why doesn't the language specification allow this kind of special use of map indexing (or type assertion or channel receive, both of which can also utilize the "comma ok" idiom) in return statements? That's a good question. My guess: to keep the language specification simple.
I'm no Go expert but I believe you are getting compile time error when you are trying to return the array i.e. return all[id]. The reason could be because the functions return type is specially mentioned as (Info, bool) and when you are doing return all[id] it can't map the return type of all[id] to (Info, bool).
However the solution mentioned above, the variables being returned i and ok are the same that are mentioned in the return type of the function (i Info, ok bool) and hence the compiler knows what it's returning as opposed to just doing (i Info, ok bool).
By default, maps in golang return a single value when accessing a key
https://blog.golang.org/go-maps-in-action
Hence, return all[id] won't compile for a function that expects 2 return values.
I was able to store functions into a table. But now I have no idea of how to invoke them. The final table will have about 100 calls, so if possible, I'd like to invoke them as if in a foreach loop. Thanks!
Here is how the table was defined:
game_level_hints = game_level_hints or {}
game_level_hints.levels = {}
game_level_hints.levels["level0"] = function()
return
{
[on_scene("scene0")] =
{
talk("hint0"),
talk("hint1"),
talk("hint2")
},
[on_scene("scene1")] =
{
talk("hint0"),
talk("hint1"),
talk("hint2")
}
}
end
Aaand the function definitions:
function on_scene(sceneId)
-- some code
return sceneId
end
function talk(areaId)
-- some code
return areaId
end
EDIT:
I modified the functions so they'll have a little more context. Basically, they return strings now. And what I was hoping to happen is that at then end of invoking the functions, I'll have a table (ideally the levels table) containing all these strings.
Short answer: to call a function (reference) stored in an array, you just add (parameters), as you'd normally do:
local function func(a,b,c) return a,b,c end
local a = {myfunc = func}
print(a.myfunc(3,4,5)) -- prints 3,4,5
In fact, you can simplify this to
local a = {myfunc = function(a,b,c) return a,b,c end}
print(a.myfunc(3,4,5)) -- prints 3,4,5
Long answer: You don't describe what your expected results are, but what you wrote is likely not to do what you expect it to do. Take this fragment:
game_level_hints.levels["level0"] = function()
return
{
[on_scene("scene0")] =
{
talk("hint0"),
}
}
end
[This paragraph no longer applies after the question has been updated] You reference on_scene and talk functions, but you don't "store" those functions in the table (since you explicitly referenced them in your question, I presume the question is about these functions). You actually call these functions and store the values they return (they both return nil), so when this fragment is executed, you get "table index is nil" error as you are trying to store nil using nil as the index.
If you want to call the function you stored in game_level_hints.levels["level0"], you just do game_level_hints.levels["level0"]()
Using what you guys answered and commented, I was able to come up with the following code as a solution:
asd = game_level_hints.levels["level0"]()
Now, asd contains the area strings I need. Although ideally, I intended to be able to access the data like:
asd[1][1]
accessing it like:
asd["scene0"][1]
to retrieve the area data would suffice. I'll just have to work around the keys.
Thanks, guys.
It's not really clear what you're trying to do. Inside your anonymous function, you're returning a table that uses on_scene's return value as keys. But your on_scene doesn't return anything. Same thing for talk.
I'm going to assume that you wanted on_scene and talk to get called when invoking each levels in your game_level_hints table.
If so, this is how you can do it:
local maxlevel = 99
for i = 0, maxlevel do
game_level_hints.levels["level" .. i] = function()
on_scene("scene" .. i)
talk("hint" .. i)
end
end
-- ...
for levelname, levelfunc in pairs(game_level_hints.levels) do
levelfunc()
end