Redefining TCL foreach - foreach

I would like to redefine TCL's foreach, since multiple applications of foreach break some code.
Detailed problem description
The actual case where the code breaks happens in Vivado, a program using TCL for scripting. They supply an API that specifies get_<someObject> methods, which returns a list of objects (actually something that behaves like a list, but is implemented by xilinx to handle caching/printing a bit differently). To handle these lists I use foreach. The first time I use foreach on the list, I get <objects> in the loop variable.
However, if I apply foreach on a single object, the object is converted into a string representing its name. The problem is, that the API function get_property expects an object.
While applying foreach twice, does not seem to make sense, this might happen if you write two functions that take a list of objects and operate on them.
i.e.
proc a {obj} {
puts "logging [llength $obj] objects:"
foreach o $obj {
puts "$o has column index [get_property COLUMN_INDEX $o]"
}
}
proc b {obj} {
foreach o $obj {
a $o
puts "working on $o"
get_property COLUMN_INDEX $o
}
}
If we now call these functions as follows
a [get_clock_regions X0Y0] # ok (the list is turned into single objects in foreach)
b [get_clock_regions X0Y0] # crashes inside a (the list from get_clock_regions is
# turned into objects by the foreach in b
# a is then called with a single object,
# the foreach now turns the object into a string
# representing the name, but get_property
# does not work on strings => error
I asked if the behaviour can be fixed in this question on the Xilinx Forums, however I am looking for a workaround for the meantime.
What I am trying to do
I would like to implement a workaround for the meantime. While I can do
a [list $o]
inside b, I think it would be nicer if I can redefine foreach to not break the above case. This way, I can simply drop my redefinition of foreach if Xilinx can fix the behaviour. (I am expecting foreach to work the same regardless if I have a list with one element or a single element, to my understanding this is the same in TCL).
My issues with redefining foreach are:
How do I know if foreach is called as
foreach {varA varB} {valueList} {...}
foreach {varA varB} {valueList1 valueList2} {...}
Is there a way to test if I have an object or a list containing one object? The Idea is two detect if it is just an object, if so wrap it into a list, which then can be unwrapped back to object by the normal foreach, however I have no clue how to detect this case.
Outline code I would like to write:
proc safeForeach {varnames valueLists body} {
if { thereAreMultiple valueLists } { # this issue no 1
foreach valueList $valueLists {
if {wouldDecayToString $valueLists} { # this is issue no 2
set valueLists [list $valueLists]
}
}
} else {
if {wouldDecayToString $valueLists} { # this is issue no 2 again
set valueLists [list $valueLists]
}
}
#the next line should be wraped in `uplevel`
foreach $varnames $valueLists $body
}

The root cause of the problem is (using your example) invoking proc a, which expects a list, with only a single scalar value when it is called in proc b. Your "workaround" of invoking a as, a [list $o], is the solution. It converts a single value into a list of one element. A list containing one element is not the same as a single value. Since lists in Tcl are just specially formatted strings, if the argument to proc a contains whitespace it will be treated as a list, split up into the whitespace separated components. Although Tcl is flexible enough to allow you to radically redefine the language, I think this is a case of "just because you can, doesn't mean you should." I just don't think this case is compelling enough since some code refactoring would make the problem disappear.

Ultimately, the issue is that you don't want to treat simple values as lists. One of the ways of dealing with that is indeed to use [list $a] to make a list out of the value that shouldn't be mistreated, but another is to change the a procedure to take multiple arguments so that you can treat them as a list internally while having quoting automatically applied:
# The args argument variable is special
proc a {args} {
puts "logging [llength $args] objects:"
foreach o $args {
puts "$o has column index [get_property COLUMN_INDEX $o]"
}
}
Then you can call it like this:
a $o
When passing in a list to a procedure like this, you want to use expansion syntax:
a {*}[get_clock_regions X0Y0]
That leading {*} is a pseudo-operator in Tcl, which means to interpret the rest of the argument as a list and to pass the words in the list as their own arguments.

Related

How to add a copy of an object instead of reference to it

So - I am doping a loop in F# with some complex logic in it so I am using a System.Collections.Generic.List so I can add to it in the loop.
What I am finding though - is that when I add an item to the list - it still somehow has a reference to the variable so when I change the "currentPostCodeRange" variable, then all of the previous additions to the list are changed as well! is there a way I can assign a "copy" of the variable somehow so it doesn't reference every single item..?
let postcodeRanges: System.Collections.Generic.List<Postcode.PostcodeRange>
= new System.Collections.Generic.List<Postcode.PostcodeRange>()
let mutable currentPostCodeRange: Postcode.PostcodeRange = { RangeType = Postcode.RangeType.Normal; From="0001"; To="0001" }
Loop:
for postCode in 1 .. 9999 do
.....
if nextPostCodeisRural <> thisPostCodeisRural then
// this is the last one in this Range
currentPostCodeRange.To <- thisPostCodeString
postcodeRanges.Add(currentPostCodeRange)
.... etc, other logic
I think the easiest way to copy a record in F# is with a copy and update record expression. I strongly recommend against adding mutable objects to collections, though, precisely because it creates the aliasing problem you're seeing here. However, if you're determined to do it, you can add a copy like this:
postcodeRanges.Add({ currentPostCodeRange with To = currentPostCodeRange.To })
You have to include at least one field in the expression, so in this case, I've explicitly copied the To field, and implicitly copied the rest. It doesn't matter which one you pick.
Again, I strongly recommend against this sort of design. I think you're better off in the long run using a scan, or some other functional technique.

dart removeWhere() - where does the data go?

I am trying to write a function in dart that takes a string that has some words that be begin with a "#" character and split it into two sets. One that contains string with only the "#" character and one with no "#" characters.
There are some obvious ways i could do this with a for loop, but want to use these fancy list processing functions (what are these called exactly?) like where() forEach().
so here is my attempt.
void main() {
String inputText = "Hello world. #hithere";
inputText.split(" ").where((element) => element.startsWith("#"))
.forEach((item) {
print(item);
});
inputText.split(" ").removeWhere((element) => element.startsWith("#"));
print(inputText);
}
Here is the output of the program:
#hithere
Hello world. #hithere
the first part works as expected, but the second part i expected the removeWhere would remove the element #hithere from my list....
but this this didnt happen.
So my question is this. Did the removeWhere() method remove this element correctly? If so where is the list that has this element removed? How do i get access to it?
my explanation of what happend is that the split(" ") method created a List and the removeWhere() method operated on this List and removed the element i told it to... but what i dont understand is how i can get access to this list? where does this list exist?
what i was think i should do is something like this:
inputText.split(" ").removeWhere((element) => element.startsWith("#")).join();
I was hoping that i could take the List with the removed elements and join() them back into a string... but since the removeWhere() method returns void.. i have no idea where the list that has removed elements exists?

Can Lua support case-insensitive method calls?

I'm using Lua as a data description language for my C++ app. I have a bunch of C++ classes bound to Lua using SLB 2.0. I have methods bound such as 'SetPos' or 'SetName'. I specify the position or name (for example) using a table with values keyed as 'pos' or 'name'. I want to be able to take the key, prepend 'set', and call the method, if it exists (it may not). Is that possible? If so, any suggestions?
I know I could make my bound methods lower case, but I'd rather keep them the same as the methods they're bound to (that may be my fallback though). I could try to build the method name based on my naming standards, but case insensitivity is less error prone.
I feel there should be a tricky piece of Lua that could solve this using metatables, but I haven't been able to work it out myself.
Any suggestions?
Thanks!
Case insensitivity is not really something Lua handles. All table lookups and local variable accesses are ultimately case sensitive string compares.
The best solution would be to just accept that you're dealing with a case sensitive system, just like C++, and deal with it.
However, if you really want to, you can do this. The simplest way would be to put every possible case permutation of a name in your function table. So your function table would have this:
["setname"] = theFunction,
["Setname"] = theFunction,
["sEtname"] = theFunction,
["SEtname"] = theFunction,
...
You can of course automate this with a function that takes each name in the table and replicates its data based on the case permutations.
A more involved but easier to use mechanism would be to use the __index and __newindex metamethods along with the empty table trick.
function CreateCaseInsensitiveTable()
local metatbl = {}
function metatbl.__index(table, key)
if(type(key) == "string") then
key = key:lower()
end
return rawget(table, key)
end
function metatbl.__newindex(table, key, value)
if(type(key) == "string") then
key = key:lower()
end
rawset(table, key, value)
end
local ret = {}
setmetatable(ret, metatbl)
return ret
end
Instead of creating a table with {}, you create the table with this function call. The table should otherwise function as normal (though obviously member access will be slightly slower).

Updating "it" inside a Groovy closure

I have a domain class that is just a list of strings (youtubeLinks).
When saving these links I want to strip out the video ID and save it instead of the entire URL entered on the UI side.
This is what I'm trying (ignore that the regex is flawed)
youtubeLinks.each {
def youtubeRegex = /v=(.*)/
def matcher = ( it =~ youtubeRegex )
it = matcher[0][1]
}
When I save this, it saves the original value of "it". Is there a way to update this reference and have it save properly?
Thanks.
Groovy's each loop is merely an iterator, and as such it neither affects the collection on which it operates, nor returns a value of its own. It's basically equivalent to Java's "advanced for loop (for-each)," only with the convenience of dynamic typing and an implicit loop variable (it). While it can be modified, it's a futile enterprise, as you'd be simply changing a reference to the original value, not the value itself. See this question for more on that.
When you need to modify every element within a collection somehow, the idiomatic Groovy (Grails) solution is to use the collect method. Collect transforms each element via the closure you provide, ultimately returning a new collection ( so, it doesn't actually "modify" anything).
Basically, you'll probably want to do something like this:
def links = '''http://www.youtube.com/watch?v=fl6s1x9j4QQ
http://www.youtube.com/watch?v=tCvMKcNJCAY
'''
assert (links =~ /watch\?v=(.*)/).collect{match -> match[1]} == ["fl6s1x9j4QQ", "tCvMKcNJCAY"]
..Though there are actually a number of ways one could go about such a task in Groovy.
Additionally, Ted Naleid's blog has some nice examples of Groovy pattern matching that you may find useful.
Edit
Here are several ways in which you could abbreviate the solution you submitted:
youtubeLinks = youtubeLinks.collect{link -> (link =~ /\?v=(.*)$/)[0][1]}
or
youtubeLinks = youtubeLinks.collect{link -> link.replaceAll(/^.*\?v=/, "") }
or this (Though it's a little contrived)
youtubeLinks = youtubeLinks.join('\n').replaceAll(/.*\?v=/, '').split()
You were right, it ended up being like
youtubeLinks = youtubeLinks.collect {
def youtubeRegex = /v=(.*)[&]/
def matcher = ( it =~ youtubeRegex )
return matcher[0][1]
}
Thanks, Northover.

The 'tap' method on String object doesn't return expected result

I ran in to an interesting problem while using the 'tap' method on objects of type 'String'.
"abc".tap { |o| o = "xyz" } # this line returns "abc" instead of "xyz"
The 'tap' method works on objects of other types.
[].tap { |o| o << "xyz" } # this line returns ["xyz"] as expected
I am using Rails 2.3.2 and Ruby 1.8.6 on Windows XP.
What am I missing here?
Update 1: I resolved this issue. It was an usage error on my part. In the first scenario I was re-assigning the value to the block parameter instead of modifying it. I was able to rewrite the code and get the expected result.
"abc".tap { |o| o.replace "xyz" }
Update 2: Code used here is just to demonstrate the problem. My actual code does not look like this.
Object#tap always returns the original object passed into it after executing the block, even if the block returns something different.
The benefit here is that you can put tap into the middle of a chain and test the value of an object without modifying the original value.
This means that if you pass "abc" into tap, it'll execute the block and return "abc". Your assignment to o doesn't mean anything due to scoping. Likewise, if you pass an empty array into tap, it would return an empty array back. However, in your second example, you modified the original value. Operations that modify the original such as << or gsub! or likewise will modify the object before its returned, therefore you get a different value back.
Check out http://moonbase.rydia.net/mental/blog/programming/eavesdropping-on-expressions for some more cool examples about how to use tap. Don't use it for assignment or modification or you'll get back wonky results.
Update: To your edit, why does that resolve your issue? I don't understand why you'd call tap to do a replace when you can just call replace on the object itself. What benefit is tap providing you?

Resources