Variable variables in Progress 4GL - progress-4gl

Is there a way to dynamically reference a variable? Apparently value() does not work on a variable reference.
def var export-columns as char extent.
def var i as int.
def var my-columns as char extent ["column1, column2"].
export-columns = value("my-columns").
do i = 1 to extent(export-columns):
put export-columns[i].
end.

The only way to dynamically access variables is if they're in a temp-table. local variables cannot be accessed dynamically.

Related

How to concat parameter of a function within a variable name

I may have not asked the question correctly but let say I want to use the name of whatever parameter i pass in to my function, to have my variable within that function to be named ;
def myFunc(dfName: DataFrame): Unit = {
val "{dfName}_concatenated" = dfName
}
so if i passed in myFunc(testDf) the variable inside should be named testDf_concatenated
Values and variables have to be named at compile time and this process you're looking for needs to be done at runtime, so you can not do it this way, try using a simple name and the value would be a Map("{whatever}_concatenated" -> ...).
I am really not sure what is your question, will that work for you?
def myFunc(dfName: String, anotherParam: Int): Unit = {
val dfNameConcatenated = s"${dfName}_concatenated"
}

class needs to be abstract since its members are not instantiated

I am trying to create a class rat having parameters "value" and "dimensions". Rat has a member "fitness". I want this member to be initialized by constructor, but declaring this member enforces it to be explicitly instantiated.
This is a class rat having a member fitness. I have declared but not defined the member as I want to get it through constructor.
class rat(value:Int,dimensions:Int){
var fitness:Int
def rat(){
fitness=sol_fit()
}
def sol_fit():Int={
var f=value*dimensions
f
}
}
This looks like a really bad design for a class. I question nearly everything about it. But it's easy enough to make it compile: just give the var a default value.
var fitness:Int = _
Now it compiles but the value of fitness will remain at default (0 in this case) because you have defined the method to calculate the proper fitness value but it is never invoked so the fitness value is unchanged.
But really, why go through all the rigamarole? Why not just initialize it with the calculated value? Why not var fitness:Int = sol_fit() or simply var fitness:Int = value*dimensions?
The constructor is the block following the class declaration, so it is OK to write this:
class rat(value: Int, dimensions: Int) {
val fitness: Int = value*dimensions
}
The expression value*dimensions will be computed when an instance of the class is created, and placed in the class memory as an Int value. When the fitness member is accessed, the value will be retrieved from the class memory and returned; it will not be re-computed.
If fitness had been declared using def rather than val, then the expression would be computed each time fitness was accessed.
If fitness had been declared using var then the value could be replaced with a new value, and any subsequent access to fitness would return the new value.

How to get a reference to a string in Scala and modify the original string by modifying this reference?

As I understand, strings in Scala are value types:
var a = "hello"
var b = a
b = "hi"
-
println(a) // hello
println(b) // hi
I want a to point to b and make code above print
hi
hi
Is this possible?
Warning: This is very bad functional style
Your a and b are strings. What you want is a reference to a string!
class StringRef(var s:String)
val a = new StringRef("hello")
val b = a
b.s = "Hi"
println(a.s) // Hi
println(b.s) // Hi
You can't do this because in Java/Scala everything is assigned-by-value. You can't assign a variable to directly reference another variable.
Instead you can assign both variables to contain the same reference value to a mutable object.

Can I dynamically construct a trait in Scala that is computed based on the class it extends?

I want to accomplish something a little different from standard mixins. I want to construct a trait whose new fields are computed based on the fields of the class (or trait) it extends.
For instance, if I had a class like this:
class Point {
var x: Int = 0
var y: Int = 0
}
and I wanted to produce a class like this:
class Point' {
var x: Int = 0
var y: Int = 0
var myx: Int = 0
var myy: Int = 0
}
I'd like to be able to write a function that computes the field names myx and myy and then mixes them into the class using a trait. Here's some made up psuedo-Scala for what I want to do:
def addMy(cls: Class) {
newFields = cls.fields.map( f => createField("my" + f.name, f.type) )
myTrait = createTrait(newFields)
extendClass(cls, myTrait)
}
The easiest way I can think of to achieve such a behavior would be to use Scala 2.10's Dynamic feature. Thus, Point must extend Dynamic and you can "mix in" arbitrary fields by adding the calculation logic to the member functions selectDynamic and updateDynamic. This is not quite what "mix in" actually refers to, but it nevertheless allows you to add functionality dynamically.
To ensure that it is possible to check whether a specific functionality has been mixed in, you can for instance use the following convention. In order to check whether a field is mixed in, a user can call hasMyx or has... in general. By default your implementation returns false. Each time you mix in a new field the corresponding has... function would return true.
Please note that the return type of all your mixed in fields will be Any (unless all your fields are of the same type, see for instance this question). I currently see no way to avoid a lot of casting with this design.

Mutable method parameters in Scala

Simple problem: I am subclassing a FilterInputStream in Scala, which has a read method:
public void read(byte [] b,int offset,int len)
The data being read will be put in b, but as parameters are "vals" in Scala methods, I see no way to properly subclass this. How do I set b to the data being read? The Java *InputStream really leaves me not much choice....
You can put an item into b at index i simply by doing b(i) = whatever. That b is a val doesn't have an effect on this. It just means that you can't reassign b (which wouldn't be useful to do anyway).
Just declaring something as a val instead of a var in Scala doesn't make it immutable. In fact, var can name an immutable value. The thing to remember is that variables in Scala, much like variables in Java, are always* references, or handles, rather than actually containing the value.
Try this in your REPL:
class Container { var content: String = "default" }
val a = new Container
val b = a
b.content = "modified"
println(a.content)
When you run val b = a you are making b and a names for the same thing (not a copy, the exact same instance of Container). Because of this, when you run b.content = "modified" the change is reflected in a as well; it is just another name for the same thing. Note this happens even though a is a val. All the val means is that you can't change what instance a is a name for.
Now think about this slight variation:
class Container { var content: String = "default" }
def update(c: Container) { c.content = "modified" }
val a = new Container
update(a)
println(a.content)
When you call update, its parameter c is also a reference or alias for a. So changes are reflected outside the method call the same way they are in the earlier example.
Arrays are mutable, so they work like this as well.
*: Primitive variables (bytes, doubles, ints, etc.) are not references in Java; their boxed equivalents (java.lang.Byte...) are. It doesn't show that much since these classes/types are immutable anyway.
def read(b: Array[Byte], offset: Int, len: Int): Unit
is equivanet to following in Java:
public void read(final byte[] b, final int offset, final int len)
The array b is still mutable, and you can modify its contents.