Comments (10)
This is an interesting idea, and wouldn't be too difficult to implement. I guess it's use would be dealing with UI controls. But I must admit, I'm not immediately sold on it!
Macros aren't usually a good idea unless Kontakt is forcing you to use them, for example with add_menu_item() or set_table_steps_shown() or for making ui_control callbacks. In your example, wouldn't it be easier and more efficient to make an array containing the UI IDs of the controls, then turn the macro into a function/taskfunc and iterate over it?
For cases where we are forced to use macros, I suppose this new functionality might be handy. I've personally never felt the need for it. Do you specific example where this would be useful?
from sublimeksp.
Sure!
For example, if you were to create a select of controls and callbacks associated with some kind of "system", or "object".
To be concrete, I may want to create a bunch of controls associated with different articulations. I want one "system" for SUSTAIN, one for STACCATO, etc. Furthermore, this system may have macro calls in a couple different places. One macro in the ICB, one macro for callbacks, one macro for listener behavior and so on.
Normally I simply do this as:
macro initBehavior(#artic#)
...
end macro
macro listenerBehavior(#artic#)
...
end macro
macro callbackBehavior(#artic#)
...
end macro
on init
initBehavior(SUSTAIN)
initBehavior(STACCATO)
...
end on
on listener
listenerBehavior(SUSTAIN)
listenerBehavior(STACCATO)
...
end on
callbackBehavior(SUSTAIN)
callbackBehavior(STACCATO)
...
This is an overly simplistic example, but it illustrates the maintainability issue of the code; when we want to edit, remove, or add an articulation, we have to find its occurrence in multiple places. This is kind of simple in this example, but for the work I do, code can be split across several files and be thousands of lines of moving parts, it becomes time consuming to try and make the code flexible by hunting down every instance of a system or object generation associated with these common literal names.
What makes more sense to me from my experience outside of KSP is this:
declare literals articulations := (SUSTAIN, STACCATO, TREMOLO, TENUTO, MARCATO, PIZZICATO, SPICCATO, PORTATO, CRESCENDO, DIMINUENDO, RIP, FALL)
on init
literate_macro(initBehavior) on articulations
end on
on listener
literate_macro(listenerBehavior) on articulations
end on
literate_macro(callbackBehavior) on articulations
from sublimeksp.
You'll notice now that maintenance has been reduced from a lot of potentially buggy moving parts to a simple code generation task abstracted AWAY from the developer by simply editing a nice master list.
Single point of (unlikely) failure.
Additionally, this grants us modularity and code independence. I can write macro code-generation systems that depend on this "articulations" literal list and not have to care what the articulations actually are. Sublime will take care of actually filling them in when I hit "compile". I can then re-use the macros for different sample libraries with different articulations but not actually have to edit anything EXCEPT for the "articulations" list itself per library.
from sublimeksp.
To provide a side point, this basically accomplishes what your current iterate_macro() already does; it simply is not limited to a set of iterable numbers and instead is extended to allow iteration over any collection of literal names. From an efficiency standpoint, I have nothing to gain by instead doing this with the current iterate_macro(), with numbers associated with those articulations since it's the same code with just different names, and I have the added disadvantage of incomprehensible code on top of that. It's a lose-lose!
from sublimeksp.
I second this request. I work the same, often having macros for ICB to declare and initialize ui components and macros to generate callbacks belonging to these ui objects. Problem is not so much the deletion of instances (if you remove code from the ICB which results in objects not being declared you're going to get compile error if the callbacks are still generated) but the other way round: An object is added in the ICB but one forgets to add the callbacks so nothing happens on ui interaction.
from sublimeksp.
I see what you mean, I used to use this method as well. However, it's no longer necessary to use macros in this way. Your idea for literate_macro() would absolutely improve using macros like this, however the best thing to do is just avoid macros as much as possible! By simply using the new UI arrays instead of macros for making controls, we can have a much nicer system. These UI arrays are of UI IDs, so rather than just duplicating code, we are actually using arrays and loops.
This also increases readability and robustness of you code:
- The program is faster because we are actually using loops and arrays rather than duplicating the same code.
- You no longer need to make macros for every circumstance (init, callback, listener).
- You can write better functions that just take integer arguments rather than duplicating functions just to receive different names.
- Much less nasty # symbols in the code.
- Your UI and data is actually organised in data structures, like arrays. While before you have to be thinking about how the code will function as just a long list of stuff.
There are still some situations where we are forced to use UI control names, rather than IDs (making callbacks for example). And this is where we can use iterate_macro().
If for example this is your code:
macro initBehavior(#artic#)
declare ui_slider #artic#Slider (0, 100)
declare ui_switch #artic#Switch
declare #artic#Variable
#artic#Slider -> picture := "graphic"
#artic#Slider -> mouse_behaviour := -500
set_bounds(#artic#Slider, 0, 10)
end macro
macro callbackBehavior(#artic#)
on ui_control(#artic#Slider)
// do something
end on
on ui_control(#artic#Switch)
// do something
end on
end macro
on init
initBehavior(SUSTAIN)
initBehavior(STACCATO)
end on
callbackBehavior(SUSTAIN)
callbackBehavior(STACCATO)
It would be much better written like this:
on init
define NUM_ARTICULATIONS := 2 // All we have to do is change this number to add/remove more articulations.
declare ui_slider articSlider[NUM_ARTICULATIONS] (0, 100)
declare ui_switch articSwitch[NUM_ARTICULATIONS]
declare articVariable[NUM_ARTICULATIONS]
declare i
for i := 0 to NUM_ARTICULATIONS - 1
articSlider[i] -> picture := "graphic"
articSlider[i] -> mouse_behaviour := -500
set_bounds(articSlider[i], 0, 10)
end for
end on
macro arcticCallbacks(#n#)
on ui_control(articSlider#n#)
message(articSlider[#n#] -> value)
end on
on ui_control(articSwitch#n#)
message(articSwitch[#n#] -> value)
end on
end macro
iterate_macro(articCallbacks) := 0 to NUM_ARTICULATIONS - 1
from sublimeksp.
Sam,
I am an experienced software developer and have carefully considered efficiency techniques using KSP. Your assumptions about the efficiency and maintainability of certain techniques (including your own proposed technique), as well as those of how I write my code (such as assuming I don't already organize ui controls into an array-based system) aren't correct at all, but I don't wish to drag out a debate here. The fact of the matter is these situations do arise in my work.
If you don't see the use for it, I will reserve time to implement it myself in the future, hopefully you will at least approve the pull request.
from sublimeksp.
I don't mean to shoot your idea down, just sharing my opinion :) In my example I perhaps should have used 'one' rather than 'you' or 'your', I wasn't trying to insinuate that your code was bad!
Anyways, yes it will do no harm having this feature. Take a look at file preprocessor_plugins file, I'm sure you will find it no trouble adding in this functionality.
from sublimeksp.
Sam,
I apologize if I seemed aggressive. Thank you for the consideration, and I will!
from sublimeksp.
As a side note, your technique DOES have a great potential for some other applications/systems. So thank you for sharing! I likely will implement it for something it works well with, and thank you for taking the time to enhance SublimeKSP to allow for it.
from sublimeksp.
Related Issues (20)
- Struct example from wiki does not compile HOT 1
- Macros containing callbacks with function calls inside are expanded within callback
- Multi-dimensional arrays fail checking for variable prefix
- Traceback Error - Upgraded package from 1.12.2 to 1.15.0 HOT 2
- Allow combinable callbacks in macros HOT 2
- UI array parsing breaks when putting pers after ui_control
- Raise error with duplicate defines
- In-line Literate_macro not allowing literals inside strings
- Another issue with Combine Callbacks option
- Autocomplete adds arguments for macros/functions
- Inline multi-line functions HOT 1
- Compilation does not take into account changes to files until they are saved. HOT 3
- Catch instances of built-in functions being used in prohibited callbacks HOT 1
- "Optimize Compiled Code" option broken for HIDE_PART_BG .or. HIDE_PART_VALUE HOT 3
- SublimeKSP Autocomplete Issue: NIKontakt Variables vs. User Variables HOT 2
- Add a .SIZE define for literal defines #416 is not working HOT 3
- new "branch optimisation" breaks existing projects HOT 2
- Improve error dialog for UICB parsing
- Enable importing .ksp files from folders (#400) broke some imports here (possible old math library related) HOT 4
- optimize_code pragma is not working HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from sublimeksp.