Jump to content

Assign() & Eval() how do they make things more difficult? (What I've read here...)


Recommended Posts

Came across a need to have a "dynamic" variable system in one of my projects. I did research only to find that most people, in the threads I read, instead suggest using arrays instead of a dynamic variable, also read some comments about Assign() and Eval() not being very useful in most cases, and could make your code uselessly complex and hard to understand. I do not see this issue with Assign() and Eval().

If I am writing a script and I need 10 specific variables that need a specific name, and specific data, without Assign()

$GFX_OBJECT = StringSplit($mROM_OBJECTS, Chr(126))
      If $GFX_OBJECT[0] >= 1 Then
         $Obj1 = $GFX_OBJECT[1]
      ElseIf $GFX_OBJECT[0] >= 2 Then
         $Obj2 = $GFX_OBJECT[2]
      ElseIf $GFX_OBJECT[0] >= 3 Then
         $Obj3 = $GFX_OBJECT[3]
      ElseIf $GFX_OBJECT[0] >= 4 Then
         $Obj4 = $GFX_OBJECT[4]
      ElseIf $GFX_OBJECT[0] >= 5 Then
         $Obj5 = $GFX_OBJECT[5]
      ElseIf $GFX_OBJECT[0] >= 6 Then
         $Obj6 = $GFX_OBJECT[6]
      ElseIf $GFX_OBJECT[0] >= 7 Then
         $Obj7 = $GFX_OBJECT[7]
      ElseIf $GFX_OBJECT[0] >= 8 Then
         $Obj8 = $GFX_OBJECT[8]
      ElseIf $GFX_OBJECT[0] >= 9 Then
         $Obj9 = $GFX_OBJECT[9]
      ElseIf $GFX_OBJECT[0] >= 10 Then
         $Obj10 = $GFX_OBJECT[10]
      EndIf

Then when I need to use $Obj1 thru $Obj10, I will have to add 10 specific If statements (or specific code) for each specific variable.

If I instead use Assign()  (with a For loop....) I achieve the same result more effeciently.

$GFX_OBJECT = StringSplit($mROM_OBJECTS, Chr(126))
        For $GFX = 1 To $GFX_OBJECT[0] Step 1
            $vName = "Obj" & $GFX
            $vData = $GFX_OBJECT[$GFX]
            Assign($vName, $vData, 2)
        Next

Then later on in the script, when I need to Use Obj1 thru $Obj10, I will use another For loop To 10 so it can use Eval() to check thru the variables and perform what's needed. You could even set a variable inside the first loop that will store $var = $Array[0] value to use later with Eval(). (For $x = 1 To $var)

There may only be few instances where you need to use Assign() and Eval() but I don't see why people say it will make the code "uselessly complex" 

Edited by coderusa
Link to comment
Share on other sites

1 hour ago, coderusa said:

and I need 10 specific variables that need a specific name

The name of a variable is "for your eyes only" and there's never any need to use a "specific name".

This wonderful site allows debugging and testing regular expressions (many flavors available). An absolute must have in your bookmarks.
Another excellent RegExp tutorial. Don't forget downloading your copy of up-to-date pcretest.exe and pcregrep.exe here
RegExp tutorial: enough to get started
PCRE v8.33 regexp documentation latest available release and currently implemented in AutoIt beta.

SQLitespeed is another feature-rich premier SQLite manager (includes import/export). Well worth a try.
SQLite Expert (freeware Personal Edition or payware Pro version) is a very useful SQLite database manager.
An excellent eBook covering almost every aspect of SQLite3: a must-read for anyone doing serious work.
SQL tutorial (covers "generic" SQL, but most of it applies to SQLite as well)
A work-in-progress SQLite3 tutorial. Don't miss other LxyzTHW pages!
SQLite official website with full documentation (may be newer than the SQLite library that comes standard with AutoIt)

Link to comment
Share on other sites

31 minutes ago, jchd said:

The name of a variable is "for your eyes only" and there's never any need to use a "specific name".

The name of a variable is important, if you just assign random variables 1) You forget what the heck you're doing 2) Its easier with a systematic variable name that has some kind of system to it other than an array, and 3) You run into trouble using the same variable names too much and end up chasing bugs you could have otherwise avoided.

1 hour ago, ioa747 said:

 

#include <Array.au3>

$mROM_OBJECTS = "Alpha~Beta~Gamma~Delta~Epsilon~Zeta~Eta~Theta~Iota~Kappa~Lambda"
$Obj = StringSplit($mROM_OBJECTS, Chr(126))

;~ _ArrayDisplay($Obj, "$Obj")

For $i = 1 To $Obj[0]
    ConsoleWrite($i & ") = " & $Obj[$i] & @CRLF)
Next

 

I like this. Only $mROM_OBJECTS = "Image1.Gif,X,Y,W,H~Image2.GIF,X,Y,W,H" etc

Then when it comes time to handle the objects,

For $x = 1 To 10 Step 1 ;Limits to 10 objects
    $vName = "Obj" & $x
    $data = StringSplit(Eval($vName), Chr(44))
    _GDIPlus_GraphicsDrawImageRect($hGfx, $data[1], $data[2], $data[3], $data[4], $data[5])
Next

To completely grasp what I am doing with Assign() and Eval() would require me to post a lot of source code and explanation, which I may do in the future, but mostly I am sharing my experience with this "uselessly complex" code :P 

Link to comment
Share on other sites

I was just telling. Your choice to persist using crap constructs or build programs in Brainfuck or Whitespace.

This wonderful site allows debugging and testing regular expressions (many flavors available). An absolute must have in your bookmarks.
Another excellent RegExp tutorial. Don't forget downloading your copy of up-to-date pcretest.exe and pcregrep.exe here
RegExp tutorial: enough to get started
PCRE v8.33 regexp documentation latest available release and currently implemented in AutoIt beta.

SQLitespeed is another feature-rich premier SQLite manager (includes import/export). Well worth a try.
SQLite Expert (freeware Personal Edition or payware Pro version) is a very useful SQLite database manager.
An excellent eBook covering almost every aspect of SQLite3: a must-read for anyone doing serious work.
SQL tutorial (covers "generic" SQL, but most of it applies to SQLite as well)
A work-in-progress SQLite3 tutorial. Don't miss other LxyzTHW pages!
SQLite official website with full documentation (may be newer than the SQLite library that comes standard with AutoIt)

Link to comment
Share on other sites

15 minutes ago, jchd said:

I was just telling. Your choice to persist using crap constructs or build programs in Brainfuck or Whitespace.

That is your opinion on it. Doing it this way seems less confusing (to me) than wasting space on repetitive code lines with a ton of arrays or random variables.  You name your variables appropriately so you don't get BrainFucked and Whitespaced trying to figure out how many times you assigned $x, and where, when you could have instead assigned $x1, $x2, $x3 and can pin point your location in the script and you have a dedicated variable to that process, a variable that can't get mixed up elsewhere in the script. The more you universalize the code the more confusing it becomes. Keep a system, and keep it standardized, it makes everything easier. 

Link to comment
Share on other sites

What is the difference between $x[1] and $x1 ?  The two brackets !  If brackets confuse you, not sure programming is for you. ;)

Beside that, you are increasing the size of your programs uselessly (by doubling all arrays into simple variables).

And in the long term, I am sure you will get bugs and issues, cause, for example, you have updated $x1 and forgot to do same in $x[1], etc.

Link to comment
Share on other sites

We could be going down the rabbit hole, but its not the issue of brackets or arrays, it's the scope of what you need and where you need it. I can agree that if you throw Assign() and Eval() all over the place you're going to get bound up into bugs. The thing about programming is that you "learn the way then find your own way." 

Let me give you a snippet. This draws up to 10 objects in one area. I don't expect you to understand what's going on here but this bit of code would be 10x longer without Assign() and Eval() and this is the only way I can get it to work WITHOUT bugs. In fact using arrays to do this made this small section of code so long and cumbersome that I spent the better part of a weekend chasing bugs. All of the variables that start with "$o" (i,e, $oName, $oData) are temporary information and do not need to be used after the loop continues or ends.

If Not ($mROM_OBJECTS = "None") Then  ;Preparing and drawing objects, if the list is not empty (None)
        $GFX_OBJECTS = StringSplit($mROM_OBJECTS, Chr(63)) ;Object List from ROM (this constant is set when the ROM loads)
        
        For $GFX = 1 To $GFX_OBJECTS[0] Step 1
            
            ;;Each Object (Obj1, Obj2 etc) is a token string separated by Chr(44) "ObjectName,ObjectPack,X,Y"
            $oName1 = "Obj" & $GFX
            $oData1 = $GFX_OBJECTS[$GFX]
            Assign($oName1, $oData1, 2)
            ;Cons($oName1 & ": " & Eval($oName1))
            
            ;;Retreiving info from .ini and loading to GDI+
            $oName2 = "oImage" & $GFX
            $ObjName = _Token($GFX_OBJECTS[$GFX], "R", "44", "2")
            $oData2 = _xIni("objects_library.ini", "OBJ-" & StringUpper($ObjName), "main_image", "R")
            Assign($oName2, _GDIPlus_ImageLoadFromFile($oData2), 2)
            ;Cons($oName2 & ": " & Eval($oName2))
            
            ;;Setting Object Location (X,Y)
            $oNameA = _Token(Eval($oName1), "R", "44", "1")
            $oPostX = _Token(Eval($oName1), "R", "44", "3")
            $oPostY = _Token(Eval($oName1), "R", "44", "4")
            
            ;;Setting Object Width/Height (W,H)
            $ObjSize = _xIni("objects_library.ini", "OBJ-" & StringUpper($ObjName), "size", "R")
            $oPostW = _Token($ObjSize, "R", "44", "1")
            $oPostH = _Token($ObjSize, "R", "44", "2")
            
            ;;Setting Object Coordinates and boundaries (cant walk over objects also use these coordinates in other places)
            $oMinX = $oPostX - $oPostW + 30
            $oMaxX = $oMinX + $oPostW + 30
            $oMinY = $oPostY - $oPostH + 10
            $oMaxY = $oMinY + $oPostH - 30
            $oCOORD = $oMinX & Chr(44) & $oMaxX & Chr(44) & $oMinY & Chr(44) & $oMaxY
            ;Cons("oCOORD: " & $oCOORD)
            
            ;;Drawing imagerect and then continueing the loop until 1 to 10 Objects (or end of list) is reached.
            $oNameX1 = "mROM_oBOUND_" & $GFX
            Assign($oNameX1, $oCOORD, 2)   ;This sets the cant walk over objects coordinates for later use
            ;Cons($oNameX1 & ": " & Eval($oNameX1))
            _GDIPlus_GraphicsDrawImageRect($hGfx, Eval($oName2), $oPostX, $oPostY, $oPostW, $oPostH)
        Next
    EndIf

I have tried various ways of writing this and this is the only way to get it work perfectly. 

 

I'll share this too. Some of you may find it useful or can make it better, I only made it for what I needed.

;---====> _Token("String,Of,Tokens", "C,R", "Chr#", "Token#Slot", "Data")
Func _Token($tokenS, $prm, $char, $tokN, $data = " ")
   $token = StringSplit($tokenS, Chr($char))
   ;_Token("String,Of,Tokens", "C", "44", "1,2,3...X" "NewToken") - Replaces Xth token with "NewToken"
   If $prm = "C" Then
     $NewTokList = " "
     For $wc = 1 To $token[0] Step 1
        If $wc = $tokN Then
            $NewTok = $data
        Else
            $NewTok = $token[$wc]
        EndIf
        
        If $NewTokList = " " Then
            $NewTokList = $NewTok
            ContinueLoop
        Else
            $TempTok = $NewTokList & Chr($char) & $NewTok
            $NewTokList = $TempTok
            ContinueLoop
        EndIf
     Next
     Return $NewTokList
     ;_Token("String,Of,Tokens", "R", "44", "1,2,3...X") - Returns Xth token from the string
   Elseif $prm = "R" Then
      $Token = StringSplit($tokenS, Chr($char))
      For $TokenSlot = 1 To $Token[0] Step 1
         If $TokenSlot = $tokN Then
            Return $Token[$tokN]
         Else
            ContinueLoop
         EndIf
      Next
      ;Debug("$token[0]", $token[0] & "$tokN: " & $tokN)
     ;Return $token[$tokN]
    EndIf
 EndFunc
 ;<====--- _Token()
 ;<===

 

Edited by coderusa
Link to comment
Share on other sites

It would be extremely unlikely that a code would only work with Assign/Eval or be most compact with it.
Especially if you consider that there is a map data type in AutoIt.

With your snippet alone, we can't really do much to make a demo of how to approach your problem instead.

If you describe the situation, add proper sample data, and especially keep the XY problem in mind, I almost guarantee you'll come out of this with a much better variant.

Link to comment
Share on other sites

13 minutes ago, AspirinJunkie said:

It would be extremely unlikely that a code would only work with Assign/Eval or be most compact with it.
Especially if you consider that there is a map data type in AutoIt.

With your snippet alone, we can't really do much to make a demo of how to approach your problem instead.

If you describe the situation, add proper sample data, and especially keep the XY problem in mind, I almost guarantee you'll come out of this with a much better variant.

I'm not having any particular issue the above snippet works perfectly in the source, more engaging in a discussion on the uses of these two functions. In fact my issue (when I had one) was fixed by Assign() and Eval() in the above snippet, at least in this scope here. The snippet is merely an example of how I've used these two functions to get around a long repetitive code, and this is the only time I need to use Assign() and Eval() in the script (apart from using it elsewhere for the $mROM_oBound_X)

It can work without Assign() and Eval() but requires much more repetition in the code. This way is tighter and, interestingly, CPU % isa little  lower this way too (only about a 2% difference on my machine)

Edited by coderusa
Link to comment
Share on other sites

The thing is that your example has little meaning without any information about the problem to be solved.
No one can conclude whether Eval/Assign is actually the most elegant variant for the corresponding problem or not.

And without this knowledge about the use case, no one can convince you with concrete facts - i.e. a better code.
Your statement that Assign/Eval is by far the best variant for a use case of yours is therefore simply irrefutable and the example does not advance the discussion.

Are you actually familiar with AutoIt maps or Scripting.Dictionary objects?

Link to comment
Share on other sites

22 minutes ago, AspirinJunkie said:

The thing is that your example has little meaning without any information about the problem to be solved.
No one can conclude whether Eval/Assign is actually the most elegant variant for the corresponding problem or not.

And without this knowledge about the use case, no one can convince you with concrete facts - i.e. a better code.
Your statement that Assign/Eval is by far the best variant for a use case of yours is therefore simply irrefutable and the example does not advance the discussion.

Are you actually familiar with AutoIt maps or Scripting.Dictionary objects?

If it has little meaning, then perhaps you're not looking outside the box. In the snippet every time Assign or Eval is used, without them there would be an additional 4 to 10 lines per object. Its meant to be looked at, pondered. There is no problem, like I said, only various ways of doing things. 

AutoIt Maps are useful but my system design is called mROM (modular read only memory) ;) which requires .ini files to do/play certain things. (thus making it modular) Sure I could load the files into a autoit map, but again, unnecessary repetition. The script loads part of the file data directly into constants and the rest of the data is fetched from the file on the fly there is no need to repeat the info for a map or object dictionary. 

 

My point is, Assign and Eval are useful and not complex, and you can use them in a loop to tighten up your script and reduce areas of error, 

Edited by coderusa
Link to comment
Share on other sites

Your example does not convince me at all.  I could rewrite your code using arrays with 25% less line, occupying less memory and running at better speed.  

Simpler, smaller, faster.  I don't know what else you can ask for...

Link to comment
Share on other sites

12 minutes ago, coderusa said:

If it has little meaning, then perhaps you're not looking outside the box.

Nope - the information you have given is not sufficient to objectively assess whether exactly this variant is the best or not.
But that's ok - I just wanted to make clear to you that the code snippet alone can't convince anyone here of Assign/Eval and the others also don't have the possibility to show you that there would have been a better possibility.
 

12 minutes ago, coderusa said:

AutoIt Maps are useful but my system design is called mROM (modular read only memory) ;) which requires .ini files to do/play certain things. (thus making it modular) Sure I could load the files into a autoit map, but again, unnecessary repetition. The script loads part of the file data directly into constants and the rest of the data is fetched from the file on the fly there is no need to repeat the info for a map or object dictionary. 

I have no idea what ini files have to do with using maps or dictionaries.
I brought them into play for another reason: Obviously the variable name is so important to you (otherwise you simply wouldn't need an assign/eval).
So it's about the assignment of a certain name - here as string - to its data.
But this is exactly what you achieve with maps.
Just without additional function calls and without creating variables which then simply live on in memory because nobody cares about their dereferencing.

Or in short: Why do you need an Eval($oName1) instead of a $mObj[$oName1] or an Assign($oNameX1, $oCOORD) instead of a $mObj[$oNameX1] = $oCOORD?

In both you have associated data with a unique name. With the latter, however, no data remains in the memory to which you have later no more access etc.

Link to comment
Share on other sites

Just now, Nine said:

Your example does not convince me at all.  I could rewrite your code using arrays with 25% less line, occupying less memory and running at better speed.  

Simpler, smaller, faster.  I don't know what else you can ask for...

Total CPU usage hasn't passed 14% on my machine.  To achieve what this script already does with just arrays the code was longer and it would not execute properly in a loop and had to be spread out in a bunch of if statements. Arrays are great, but for what I need in small portion of code, it works perfect. The benefit here is 1) Not having to deal with array subscript range errors and 2) No repeating statements. I suppose it would be more understandable if I post the entire source, but not doing that until its more complete. ;) 

Link to comment
Share on other sites

5 minutes ago, AspirinJunkie said:

Nope - the information you have given is not sufficient to objectively assess whether exactly this variant is the best or not.
But that's ok - I just wanted to make clear to you that the code snippet alone can't convince anyone here of Assign/Eval and the others also don't have the possibility to show you that there would have been a better possibility.
 

I have no idea what ini files have to do with using maps or dictionaries.
I brought them into play for another reason: Obviously the variable name is so important to you (otherwise you simply wouldn't need an assign/eval).
So it's about the assignment of a certain name - here as string - to its data.
But this is exactly what you achieve with maps.
Just without additional function calls and without creating variables which then simply live on in memory because nobody cares about their dereferencing.

Or in short: Why do you need an Eval($oName1) instead of a $mObj[$oName1] or an Assign($oNameX1, $oCOORD) instead of a $mObj[$oNameX1] = $oCOORD?

In both you have associated data with a unique name. With the latter, however, no data remains in the memory to which you have later no more access etc.

Variables are automatically destroyed after the script finishes with them, unless they are called on the global scope, correct? So any memory used is released once the variable is finished being used, correct? (According to help file). 

The variable name isn't what's important it's the way in which I found to use them. There's more than one way to skin a cat and everyone like's their own brand.  What I see is a unwritten "form" that has to be adhered to otherwise you're an idiot, even if someone -thought- of a different way, its not the beaten path so better not.... I see that a lot in all aspects of programming (and other things too). Learn the way then find your own way! :)

Link to comment
Share on other sites

But again, to the point, regardless of how its used, I fail to see the useless complexity in using Assign() and Eval(), and even then there is little difference in coding effort between those functions and using arrays. The greatest part of AutoIT is UDFs. You can expand upon anything you want and create your own system, isnt that the point of programming? Or is it to follow a set guide and form so people don't thumb their noses at your work? If it works, it works.

You tell me.

Edited by coderusa
Link to comment
Share on other sites

10 minutes ago, coderusa said:

Variables are automatically destroyed after the script finishes with them

No - variables are automatically destroyed when their scope ends. This would be the case for local variables when the function is exited.
In your case, however, you make all variables global per se. So they remain until the whole script is terminated.

With the variant per map, however, you would have the possibility of encapsulation by, for example, creating the map locally in a function and simply passing it to another function when it is called. This way you could limit the lifetime of the variables to exactly the area where they are needed.
This is not possible with youre approach - they remain until the bitter end.

You also don't have the possibility to delete the variables manually. You can only assign them other values like zero or "". The variables themselves remain in any case until the end of the script. With the map variant, however, you can delete them dynamically.

But to delete them manually you would need their names first anyway. You would have to either construct their names again or save them. So you would need your own variable management around it. With Map a MapKeys() is enough and ready.
 

25 minutes ago, coderusa said:

There's more than one way to skin a cat and everyone like's their own brand.  What I see is a unwritten "form" that has to be adhered to otherwise you're an idiot, even if someone -thought- of a different way, its not the beaten path so better not.

You can approach problems however you want. However, it was you who created this thread to convince others that Eval/Assign has advantages that other approaches do not have. The only thing is that you have not been able to convince anyone with what you have shown so far. Contradiction is of course frustrating, especially when you are so convinced yourself. But it was obviously your goal that others argue with your approach. Of course, it may be that everyone here is terribly dogmatic and stubborn on principle. Or maybe now would be the time to reflect yourself and to check if your own arguments are really valid and if they are objectively really convincing. If not, one would have to follow up argumentatively.

Link to comment
Share on other sites

6 hours ago, AspirinJunkie said:

No - variables are automatically destroyed when their scope ends. This would be the case for local variables when the function is exited.

I'm starting to think you do not understand what I'm trying to say.

Quote

A variable's scope is controlled by when and how you declare the variable.  If you declare a variable at the start of your script and outside any functions it exists in the Global scope and can be read or changed from anywhere in the script.

If you declare a variable inside a function it is in Local scope and can only be used within that same function Variables created inside functions are automatically destroyed when the function ends.

So by what the help file says, any variable set inside a function, without using Local/Global, will be destroyed when the function ends, as I stated before.

6 hours ago, AspirinJunkie said:

You can approach problems however you want. However, it was you who created this thread to convince others that Eval/Assign has advantages that other approaches do not have. The only thing is that you have not been able to convince anyone with what you have shown so far. Contradiction is of course frustrating, especially when you are so convinced yourself. But it was obviously your goal that others argue with your approach. Of course, it may be that everyone here is terribly dogmatic and stubborn on principle. Or maybe now would be the time to reflect yourself and to check if your own arguments are really valid and if they are objectively really convincing. If not, one would have to follow up argumentatively.

I can't help it if you can't read a snippet and get a basic understanding of what it does just by the functions and description available (the other users understood it, you seem to be the only one who doesn't understand). I'm not having any issues here using this method, and the point was to share with other users that people shouldn't be so "hesitant" or "scared" to use something in a an experimental way., just because a 10 year old forum thread says its a bad idea with almost no documentation on why, isn't good enough for me. I've given multiple examples and shown multiple uses for Assign() and Eval(), more than what I found searching for on this topic. 🤭

Edited by coderusa
Link to comment
Share on other sites

5 minutes ago, coderusa said:

That's not what the help file says. 

That is what AutoIt does.

7 minutes ago, coderusa said:

So by what the help file says, any variable set inside a function, without using Local/Global, will be destroyed when the function ends. 

To break it down for you:

  • Case 1: Variable is declared with local keyword within a function: The variable is deleted as soon as the function reaches its end.
  • Case 2: Variable is declared with global keyword within a function: The variable is only deleted when the program ends - it also remains when the function ends.
  • Case 3: Variable is declared with Dim-Key within a function: If a global variable with this name already exists, then this global variable is used (and is not deleted when the function ends). If, on the other hand, no corresponding variable exists, the variable is declared as a local variable - see case 1.
  • Case 4: Variable is declared without keyword within a function: This is the implicit case 3
  • Case 5: Variable is created by Assign($Name, $Data, 2) within a function (your case): See case 2.
16 minutes ago, coderusa said:

I can't help it if some of you can't read a snippet and get a basic understanding of what it does just by the functions and description available

Because it makes no sense to improve a supposed solution to a problem when the problem itself is unknown.
Solid alternatives can only be generated if the basic problem is known. Everything else only leads to an XY problem to the power of 2.
But you have made it clear that you want to keep your secrets to yourself, so I won't be embarrassed to give you an alternative approach.  

21 minutes ago, coderusa said:

I'm not having any issues here using this method, and the point was to share with other users

Nobody doubts that your code works for you. It was merely noted that there are significantly better alternatives in terms of code size, clarity, performance and memory requirements. No more and no less. You just don't want to hear them or don't respond to them when they are mentioned.

23 minutes ago, coderusa said:

just because a 10 year old forum thread says its a bad idea isn't good enough for me. 

No one here has referred to a 10 year old thread - just you. On the other hand, enough arguments were presented and not just bluntly referred to any old threads.

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...