FuncSug
FuncSug is a simple alternative to event-driven programming and game loops. No main loops or event-action associations any more thanks to concurrency, waiting for specific events and a special handling of interruptions.
Install / Use
/learn @cl4cnam/FuncSugREADME
<img height="50" alt="Funcy_logo" src="https://github.com/user-attachments/assets/b9ad10d5-65f3-460f-b660-a8e265a13db8" /> FuncSug – A language to express concurrent and sequential behaviors structuredly
<p align="center"> <img src="https://github.com/user-attachments/assets/1b64ac3e-6701-4427-9670-5b34659819c0" alt="When a branch is finished the other branch is definitively interrupted" width="450"> <br> <em>When a branch is finished the other branch is definitively interrupted</em> <br> <br> <img src="https://github.com/user-attachments/assets/c5ab6dd8-143b-4aaf-a5ef-1bf0514f30be" alt="code" width="450"> </p><br> <br>
<p align="center"> <a href="https://cl4cnam.github.io/try_FuncSug/?example=drinkingCow"> <img width="380" height="201" alt="logoCawPG" src="https://github.com/user-attachments/assets/474f001b-35e8-4e16-84d4-e0b29e2d9aa2" /></a> </p><br> <br>
🔄No mandatory main loop any more
FuncSug is an experimental dynamic language that aims to simplify GUI programming in browser, as a complement to JavaScript. The convenience is that FuncSug doesn't force you to structure your code according to an event loop or a game loop.
To grasp the specificity of FuncSug, the easiest way is to visit the 🕹️playground.
👉 🧪Online Playground with complete examples (including 🕹️mini-games) 👈
🎓Tutorials - 🌱Getting started - 🧩Examples - 🧵REPL
<br>
<br>
🎯The main goal of FuncSug might be painted as follows:
<img width="843" height="547" alt="noSlice" src="https://github.com/user-attachments/assets/64ef968a-6bbb-432d-92cb-67f69696dd58" />FuncSug enables a more linear code in line with async/await and structured concurrency. It replaces event-driven code structures with easy-to-use seemingly parallel syntaxes (without using OS threads). It allows you to program like the event loop doesn't exist (Not replaced by a game loop either).
🧩 A few samples
🎶 🎶 Play multiple sounds at the same time
parallel ||
playSoundFile('sound1.mp3')
||
playSoundFile('sound2.mp3')
||
playSoundFile('sound3.mp3')
🎶 🔁 Play multiple sounds one at a time
playSoundFile('sound1.mp3')
playSoundFile('sound2.mp3')
playSoundFile('sound3.mp3')
⏱️Timeouts
displayNewMessage('What is ...?')
parallel exitAfter 1 finished ||
var theAnswer := awaitHumanText()
||
waitSeconds(15)
🔘A simple choice
displayNewMessage('<button id="A">I choose A</button> <button id="B">I choose B</button>')
parallel(select 1) ||
||=================
awaitClickBeep('#A')
...---
displayNewMessage("You've chosen A")
||================
awaitClickBeep('#B')
...---
displayNewMessage("You've chosen B")
🔧A less simple choice
displayNewMessage(`
<button id="A">I choose A</button>
<button id="B">I choose B</button>
`)
parallel(select 1) ||
||=================
awaitClickBeep('#A')
displayNewMessage('<button id="Aconfirmed">Yes, I choose A</button>')
awaitClickBeep('#Aconfirmed')
...---
displayNewMessage("You've chosen A")
||================
awaitClickBeep('#B')
...---
displayNewMessage("You've chosen B")
||================
waitSeconds(5)
...---
displayNewMessage("You've hesitated")
🤔 Why
Many people ask why GUI programming is so difficult. Some of common difficulties come from event-driven programming problems. That's why, with FuncSug, programmers do NOT have to follow the event-driven programming paradigm. For example, you no longer link an event to an action (like "addEventListener" does) and so no longer have the corresponding problems.
⚙️How
FuncSug suppresses event-driven programming problems: callback hell and state management.
⭐Advantages:
- It avoids callback hell (You don't need callback any more).
- Your code follows the order of execution so you avoid spaghetti code and debug more easily.
- It solves the state management problem (It eliminates the need to manage all the combinations of component states).
- It easily manages task cancellations (including task timeouts).
- It can detect a change in the value of a variable and react accordingly.
- It's deterministic.
- (You can also include JavaScript snippets, pass FuncSug variables to it and get back JavaScript return).
⚙️by means of:
- explicit logical parallelism,
- block cancellations,
- and "
awaitevent" instructions.
Please, let me know what you think (Github discussions, Mastodon).<br> I'd be happy to read your opinion and answer your questions.
↔️Compare
These two codes do the same thing (on mobile, please scroll right to see the FuncSug code):
<table> <tr> <th align="center">JavaScript/DOM</th> <th align="center">FuncSug</th> </tr> <tr> <td>let numberOfClick
function $(id) {
return document.getElementById(id)
}
function launch() {
$('launch').removeEventListener('click', launch)
setTimeout(
()=>{
$('clickZone')
.removeEventListener('click', clickZone)
console.log("Good job! See you soon!")
},
30000
)
numberOfClick = 0
$('clickZone')
.addEventListener('click', clickZone)
}
let timeoutID
function clickZone() {
if (numberOfClick == 0) {
timeoutID = setTimeout(
()=>{
if (numberOfClick < 3) {
numberOfClick = 0
console.log("Non-triple click")
}
},
2000
)
}
numberOfClick += 1
if (numberOfClick == 3) {
numberOfClick = 0
console.log("Triple click")
clearTimeout(timeoutID)
}
}
$('launch').addEventListener('click', launch)
</td>
<td>
awaitClickBeep('#launch')
parallel exitAfter 1 finished ||
waitSeconds(30)
||
while true:
awaitClickBeep('#clickZone')
parallel exitAfter 1 finished ||
awaitClickBeep('#clickZone')
awaitClickBeep('#clickZone')
print("Triple click")
||
waitSeconds(2)
print("Non-triple click")
print("Good job! See you soon!")
</td>
</tr>
</table>
If you copy and paste, replace each three initial spaces by one tabulation (Github markdown doesn't allow to change tabulation size in this context).
👀Get a taste of the language
Have a look at:
<!-- C'est un commentaire à ne pas retirer de suite au cas où <p align="center"> <a href="https://github.com/cl4cnam/Memory/blob/main/memory.fg"> <img <img src="https://github.com/user-attachments/assets/90df278a-527b-4d49-b283-bb0e7957ca7f" width="60" alt="Memory"><br> <sub>trio Memory game</sub> </a> <a href="URL_2"> <img src="IMG_2" width="60" alt="Hypertext fiction"><br> <sub>Hypertext fiction</sub> </a> <a href="URL_3"> <img src="IMG_3" width="60" alt="Guess the number"><br> <sub>Guess the number</sub> </a> </p> -->- 'Memory' code or play now.
- 'Memory2' code or play now.
- 'Hypertext fiction' code or play now.
- the 'Make Gems' code or play now.
- 'Guess the Number' code or play now.
- 'Mini Sweet' code or play now.
- 'Aquarium' code or play now.
Look at the global structure of the code: One cannot follow this structure in usual programming language.
Let's take, for example, the 'Make Gems' code:
In this language, there is no need to build a ball object, just call a function lifeOfBall.
You just run multiple lifeOfBall, birthOfGem and a lifeOfPaddle in parallel.
These functions do not build objects: they are just like any classical function.
<br>
In the body of lifeOfPaddle, just code the various behaviors of the ball in parallel.
In 'Guess the Number', gameCourse is just a function. The line just after the call of gameCourse is executed only when the player has found the number, that is
Related Skills
pestel-analysis
Analyze political, economic, social, technological, environmental, and legal forces
next
A beautifully designed, floating Pomodoro timer that respects your workspace.
product-manager-skills
46PM skill for Claude Code, Codex, Cursor, and Windsurf: diagnose SaaS metrics, critique PRDs, plan roadmaps, run discovery, and coach PM career transitions.
devplan-mcp-server
3MCP server for generating development plans, project roadmaps, and task breakdowns for Claude Code. Turn project ideas into paint-by-numbers implementation plans.
