Jump to content

Sky Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate
Photo

Standard Library (stdlib): Simple file-system approach


  • Please log in to reply
63 replies to this topic

Poll: Should each stdlib function name begin with an underscore? (8 member(s) have cast votes)

Should each stdlib function name begin with an underscore?

  1. Yes, to reduce competition with user function names and indicate at-a-glance that the function is external. (1 votes [12.50%])

    Percentage of vote: 12.50%

  2. No, it's better not to "penalize" stdlib functions in this way. (7 votes [87.50%])

    Percentage of vote: 87.50%

  3. Other (0 votes [0.00%])

    Percentage of vote: 0.00%

Vote Guests cannot vote
majkinetor
  • Moderators
  • 4512 posts
  • Last active: May 20 2019 07:41 AM
  • Joined: 24 May 2006

But I like the "@" since it reflects the dependency to a modul/class.

# and @ look very ugly in function names. I bet many users will be discouriaged to use stdlib functions just because of names that remind on some garbage. Plus you can't esaily spot where function begins (at least I can't).

GDIplus#Start()   
GDIplus#Stop() 
GDIplus#LoadBitmap()

[email protected]() 
[email protected]() 
[email protected]()

GDIplus_Start() 
GDIplus_Stop() 
GDIplus_LoadBitmap()

Well, this is trivial thing, we just need to decide...
Posted Image

toralf
  • Moderators
  • 4035 posts
  • Last active: Aug 20 2014 04:23 PM
  • Joined: 31 Jan 2005
One reason the init function is nice, is that it cuts number of searches in half. No need to search for Name_Function.ahk and then Name.ahk. And an init function would follow the 1-1 principle.

Of cause with an "@"/"_" AHK could limit the search directly to the modul/class file. This would then be an exception to a 1-1 principle. But the more I think of it, I like this approach with an "@".
Ciao
toralf
 
I use the latest AHK version (1.1.15+)
Please ask questions in forum on ahkscript.org. Why?
For online reference please use these Docs.

corrupt
  • Members
  • 2558 posts
  • Last active: Nov 01 2014 03:23 PM
  • Joined: 29 Dec 2004

Having non standardized name for INIT function is not good, as users will have to read doc before using any module, as different modules will have different initialisation names. If module base name acts like INIT function ( MMenu() ) then we can use 1-1 principle without classes. The drawback would be users will have to initialise every module they use witch will lead to stdlib behaving differently then AHK language in which things usualy don't have to be initialised.

I may be wrong, but I think that modules like this will be rare since most modules will have one function that needs to be called first before a user is able to use the module or the functions will be able to be separated into separate files if the module doesn't need to be initialized first. If there is a specific function or 2 that is needed by all functions in the set but any of the functions could be called separately then maybe the functionality should be added to each function instead of having to call from one function to another each time. An alternative might be to include the function into each function file but specify a different unique function name each time. This will add complexity and design time to modifying existing functions but it might be better to modify the modules than to add additional complexity to what AutoHotkey has to do in order to know which files to Include.

If a module has a particular function that needs to be called first then the module should probably use that function as the filename and add dependent functions to the file. That way the user doesn't have to remember to initialize the function.

Another possible consideration for init() functions and large, complex modules is that most users will likely need to read a manual to be able to know how to use the module and know which functions to use anyway. In the process they will see that they have to call an init() function first.

toralf
  • Moderators
  • 4035 posts
  • Last active: Aug 20 2014 04:23 PM
  • Joined: 31 Jan 2005

# and @ look very ugly in function names. I bet many users will be discouriaged to use stdlib functions just because of names that remind on some garbage. Plus you can't esaily spot where function begins (at least I can't).

True, it isn't very nice. But how often will a user use modules? I think most people will write their own functions and I would not like to be restricted to use _ in my function names. Of cause if I write a function and include it into the script (or via the #include command) AHK wouldn't include the lib file with the same name. But I can't forsee when this will be come a problem with complex moduls. I'm unsure what is best. "_" seems to be easier to read but is used often which might (?) introduce name conflicts.
Ciao
toralf
 
I use the latest AHK version (1.1.15+)
Please ask questions in forum on ahkscript.org. Why?
For online reference please use these Docs.

majkinetor
  • Moderators
  • 4512 posts
  • Last active: May 20 2019 07:41 AM
  • Joined: 24 May 2006

I may be wrong, but I think that modules like this will be rare
...
or the functions will be able to be separated into separate files if the module doesn't need to be initialized first.

Your opinion is extremely subjective now.

First, module requiring init for arbitrary function call is not rare thing. API wrappers are most common example. Furthermore, as stdlib will use lot of API functions, and it is generaly pain for ppl to create good DllCalls, I would like to see API category in stdlib containing all API functions wrapped so far while implementing stdlib own functions. In other words, if your (trivial) module requres API call, you will wrapp it, and provide it as a stdlib feature so other ppl can use this wrapper in the future for their own needs. If you don't do that, we will end up with mass of differnt private wrappers around stdlib.

Example: MMenu uses 70% of Windows Menu SDK. I dont' see why those API wrappers shouldn't be exposed to stdlib users as the other alternative is to use API wrappers privately (so they will exist again, just will not be documented/standardised). This is bad because by letting API wrappers to be public we can soon have large database of ready API's to use with AHK, without DllCalls. This will basicly kill the need for DllCalls in most cases as most common Win API functions will be at some momemnt available via stdlib.

Another example is Philho's DLLPlus or Holominds GDI wrapper, Seans CoHelper etc.. there are number of wrappers around the forum and wiki that were never organised. This is good place to solve this problem too.

I think most people will write their own functions and I would not like to be restricted to use _ in my function names.

U can use _ in your own functions with this approach. If you declared function with name Blabla_blabla, it will not be searched in library.
Posted Image

corrupt
  • Members
  • 2558 posts
  • Last active: Nov 01 2014 03:23 PM
  • Joined: 29 Dec 2004
Using @ is an interesting idea that might work ok (as was mentioned). If a function name contains a @ character then only the first part of the name could be used for searching for the file to include (eg. [email protected] would search for the MyFunct.ahk file).

majkinetor
  • Moderators
  • 4512 posts
  • Last active: May 20 2019 07:41 AM
  • Joined: 24 May 2006
@ is definitely used to much lesser extent then _ in function names.

Its funny though... it looks like module is part of the function ( MMenu AT Create, contrary to real situation - Create AT MMenu)
Posted Image

corrupt
  • Members
  • 2558 posts
  • Last active: Nov 01 2014 03:23 PM
  • Joined: 29 Dec 2004

I think most people will write their own functions and I would not like to be restricted to use _ in my function names.

That wasn't me. That was toralf ;)

corrupt
  • Members
  • 2558 posts
  • Last active: Nov 01 2014 03:23 PM
  • Joined: 29 Dec 2004

@ is definitely used to much lesser extent then _ in function names.

True. and since we had discussed only allowing alpha numeric characters for stdlib functions, it would be even less likely :) .

Chris
  • Administrators
  • 10727 posts
  • Last active:
  • Joined: 02 Mar 2004

So with no recursion it is 4 look ups at worst with average 2 probably. Lets forget about recursion then.

Maybe the userlib should search recursively, but not the stdlib. This would boost performance a little.

You can create index.dat on installation, and check if Include dir is changed on startup (using modification date). If it is, you can rebuild index.dat if it is not (and in 99.9% of cases it will not be changed) u can use index.dat instead using File System functions. Using this file will make recursive search instant, and any other search.

This seems complicated, so maybe it should be deferred until after the initial release (and implemented only if it significantly boosts performance).

I think that you maybe have a point with double underscore. We can make a rule that double _ is class separator and that it will be included as described above without looking for entire construct as file name.

After reconsidering, I think double-underscore might be bad because it's sometimes hard to visually distinguish between a double and a single underscore. Also, it would lead to the undesirable restriction that function names can never legitimately contain double underscores (unless they're classes).

Using a "#" or "@" for modul/class functions would remove the requirement to not name a new lib function SSFName_Function. But it would just add a new requirement just with the new symbols. But I like the "@" since it reflects the dependency to a modul/class.

@ is definitely used to much lesser extent then _ in function names.
Its funny though... it looks like module is part of the function ( MMenu AT Create, contrary to real situation - Create AT MMenu)

It was tentatively planned for v2 to restrict function/variable names to alphanumeric and underscore. Also, I don't think either @ or # is that friendly or readable, so maybe it's best to stick with a single underscore and search for a class name only when all other searches fail; that is, right before the program displays "Call to nonexistent function".

it would be good to reserve _ in stdlib only for classes. This is small rule and will create nicer environment. If you see _ in the name, you know it is part of some module, so you can check out the module to see what other things it offers. If you don't see _ you know it is SSF.

This might not be optimal because some functions don't read very well with InitCaps and thus underscores are preferable. For example, "LVAdd" is visually hard to see as two words, but "LV_Add" is better.

INIT function must be used for modules requiering action in autorun section

One way to do this is with static variables when they someday support function-calls as initializers; e.g. static s := random_seed_init(). Such functions would be auto-called only once, prior to the start of the auto-execute section.

Until then, a function or class can have logic that initializes itself by detecting whether a global variable is blank. If it's blank, each public function (at least ones that are ever likely to be called first) would run some extra code. For example:
Global RandomIsInitialized
if not RandomIsInitialized
	RandomInit()

#Lib U "%A_AHKPATH%\Include-User" S "%USERPROFILE%\My Documents\AHKStdLib"

I'm leaning toward the following:
#lib  ; No libraries, so no searching.
#lib path1 > path2 [> path3...]  ; explicitly named directories.
#lib ?path1  ; Use leading question mark to enable recursive search in that folder.
#lib ?*user > *std  ; This is the default so would never need to be specified.
#lib *std > ?*user  ; reverse the default order: search std before user.
#lib *std  ; stdlib only
I'm also leaning toward "My Documents\AutoHotkey UserLib" as the default userlib because the only practical alternative is to have no userlib by default (in which case it would be enabled only via registry, environment variable, or directive). Of course, "My Documents\AutoHotkey UserLib" wouldn't be created automatically. If it doesn't exist (and it usually won't for casual users), no userlib searching is done.

majkinetor
  • Moderators
  • 4512 posts
  • Last active: May 20 2019 07:41 AM
  • Joined: 24 May 2006

This seems complicated, so maybe it should be deferred until after the initial release (and implemented only if it significantly boosts performance).

This is trivial, think about it. Pseudo code:

When serch is to be done:

- FileExist( index.dat) or IndexModDate != RootModDate ?
- Yes - use search to find function and related file in the index.dat
- No - recreate index.dat and repeate.[/list]

Creation of index.dat goes something like this:
FileDelete, index.dat
FileAppend index.dat, ModificationDate
loop, root ,recurse
    If fileExt = ahk
       FileAppend, index.dat, fileNameWithoutExt, FilePath

IMO benefits of cashing are big when performance is in question and it can allow recursion etc..

For example, "LVAdd" is visually hard to see as two words, but "LV_Add" is better.

Yup, but this example is not appropriate. Something like this will be part of a module. I doubt there is need to crate SSF named LV_Add and it seems the best to use ListAdd even in that case.

One way to do this is with static variables when they someday support function-calls as initializers; e.g. static s := random_seed_init(). Such functions would be auto-called only once, prior to the start of the auto-execute section.

There is currently no easy way to use statics for configuration data when number of functions should access them. This is typical usage for my current INIT functions, to initialise global config used by all functions.

Statics can act like globals this:

Module_Function1(){

   config1 := Module_Field("config1")
   config2 := Module_Field("config2")
}

Module_Function2(){
   Module_Field("config1", 100)
   Module_Field("config3", "my text")
}

[color=red]Module_Field("name", value="") {
  static config1
  static config2
  ...
  static configN
  
 if value = 
       Return %name%
 
  %name% := %value%
      
}[/color]

This is currently the only way I see that multiple functions can use same data, available via statics. Although good as it will hide module data from outer world, it is slow for general usage.
Posted Image

Chris
  • Administrators
  • 10727 posts
  • Last active:
  • Joined: 02 Mar 2004
Perhaps caching would help if only to save the names of all nested sub-directories inside the target folder. Within each directory, the program would ask the OS, "does specific filename X exist?". Since such answers are essentially instantaneous on NTFS, no other caching is likely to be worthwhile. I've added this to my notes (though the notes are getting really long again, which threatening to exceed my energy budget :)).

By the way, in case it matters for what you were doing, I edited my post above while you were posting.

majkinetor
  • Moderators
  • 4512 posts
  • Last active: May 20 2019 07:41 AM
  • Joined: 24 May 2006

By the way, in case it matters for what you were doing, I edited my post above while you were posting.

Seems good enough for me.

Perhaps caching would help if only to save the names of all nested sub-directories inside the target folder

Indeed. The difference is still that you will have to query X folders for the name, but as you said, with NTFS is this instantious and I doubt there will be more then lets say 50 folders/categories in full blown stdlib...
Posted Image

corrupt
  • Members
  • 2558 posts
  • Last active: Nov 01 2014 03:23 PM
  • Joined: 29 Dec 2004

I'm also leaning toward "My Documents\AutoHotkey UserLib" as the default userlib

I would prefer My Documents/AutoHotkey/Include or something like UserLib instead of Include for a subdirectory. I think that the main folder should be AutoHotkey though. That way, a folder gets reserved for any user files that have anything to do with AutoHotkey. I would also create this folder and the UserLib folder during installation. If the folder doesn't get used it should get removed by the installer if the user uninstalls AutoHotkey for some strange reason. If on the other hand a user wants to add a function or two in the UserLib (not all users will likely create functions but anyone can copy and paste something from the forum and drop it in the folder to use it) they will not have to worry about misspelling or using the wrong folder name in the wrong location as the necessary folder would already exist. A readme.txt file could also be added to the folder to explain what the folder can be used for. Another possibility (although there's likely not enough energy allocated in the budget... ;) ) might be to add a couple options to the installer. If a user specifies to do a custom install then they could maybe specify whether they want to create a UserLib folder and allow them to choose where to create one if they do. The folder location could then be stored in the registry.

Chris
  • Administrators
  • 10727 posts
  • Last active:
  • Joined: 02 Mar 2004

I'm also leaning toward "My Documents\AutoHotkey UserLib" as the default userlib

I would prefer My Documents/AutoHotkey/Include or something like UserLib instead of Include for a subdirectory. I think that the main folder should be AutoHotkey though. That way, a folder gets reserved for any user files that have anything to do with AutoHotkey.

That's a reasonable alternative. Perhaps a poll and/or some public dicussion will help decide.

I would also create this folder and the UserLib folder during installation. If the folder doesn't get used it should get removed by the installer if the user uninstalls AutoHotkey for some strange reason. If on the other hand a user wants to add a function or two in the UserLib (not all users will likely create functions but anyone can copy and paste something from the forum and drop it in the folder to use it) they will not have to worry about misspelling or using the wrong folder name in the wrong location as the necessary folder would already exist.

I think it would be too invasive and non-traditional for the installer to create anything in the My Documents folder, at least by default. However, having an option in the Installer (as you suggested) might be worthwhile someday.

A readme.txt file could also be added to the folder to explain what the folder can be used for. Another possibility (although there's likely not enough energy allocated in the budget... ;) ) might be to add a couple options to the installer. If a user specifies to do a custom install then they could maybe specify whether they want to create a UserLib folder and allow them to choose where to create one if they do. The folder location could then be stored in the registry.

Yes, this seems too ambitious, especially for someone who isn't an expert in the NSIS installer language.

Thanks.