- 644
- 392 686
Stephen Blum
United States
เข้าร่วมเมื่อ 9 เม.ย. 2011
CTO at PubNub, Software Engineering, Data Mining, AI, APIs
Rust By Example: Higher Order Functions
High-order functions, a math term, means a function that receives or outputs another function for later use or both. It sounds hard, but Rust programming language makes it easy. Here's an example: suppose we want to find the sum of numbers that have odd squares under 1,000.
A complex scenario, not usually faced in daily life, but an interesting one nonetheless. We start with quite a bit of code, including a 'for' loop with an infinity operator which will stop at our limit, 1,000. It’s easy to get lost in this with all the bits and pieces and changes of direction.
But consider this, a simpler version. Just five lines of packed code that achieve the same goal, without missing the logic. How is this possible?
We create our infinity, square our number, make sure it's within limit, filter out odds, and sum. A simpler process to read and follow. Is it more efficient in terms of performance too?
Challenging to say. Both versions include a multiplication operation, which isn't cheap in computing terms. The less code version grows an array, maybe using more memory.
But in terms of readability, the shorter code clinches it. It's definitely worth exploring high-order functions for complexities like these.
A complex scenario, not usually faced in daily life, but an interesting one nonetheless. We start with quite a bit of code, including a 'for' loop with an infinity operator which will stop at our limit, 1,000. It’s easy to get lost in this with all the bits and pieces and changes of direction.
But consider this, a simpler version. Just five lines of packed code that achieve the same goal, without missing the logic. How is this possible?
We create our infinity, square our number, make sure it's within limit, filter out odds, and sum. A simpler process to read and follow. Is it more efficient in terms of performance too?
Challenging to say. Both versions include a multiplication operation, which isn't cheap in computing terms. The less code version grows an array, maybe using more memory.
But in terms of readability, the shorter code clinches it. It's definitely worth exploring high-order functions for complexities like these.
มุมมอง: 199
วีดีโอ
Python to Rust Code Migration Frequently Asked Questions
มุมมอง 349วันที่ผ่านมา
You can improve the latency of a Python service by writing some parts in Rust, compiling the Rust code into a library, and importing it into Python. This is totally possible and there are several ways to do it. One way is using Python extensions like CFFI bindings. PyO3 makes this process easier. Just write your Rust code, compile it for native Python extensions, annotate the functions you want...
Advantages of Letter based Tokenization for Machine Learning
มุมมอง 44วันที่ผ่านมา
Let's chat about letter-based tokenization in machine learning models. TikTok folks asked about the advantages of using letters for tokenization, especially when dealing with the attention mechanism. Well, there are several. Letter-based tokenization gives us fine granularity. It catches more details since it's looking at each character, which is crucial for rare words and nuanced meanings. It ...
ComfyUI Tutorial
มุมมอง 36914 วันที่ผ่านมา
ComfyUI is a tool that lets you use AI image generators like Stable Diffusion to create tons of realistic images. It’s great for things like fashion ideas, e-commerce, and advertisements. You design a workflow to specify the type of images you want and click go to generate them. You can even create storyboards for video ideas. Installing ComfyUI on Windows is simple: download, extract, and run ...
Machine Learning Batch Size
มุมมอง 7814 วันที่ผ่านมา
The batch size you use has a big impact on the machine learning model you're training and its final output. A small batch size means longer training times because it doesn't fully use your hardware. Large batch sizes, on the other hand, can quickly process data in parallel using the GPU, leading to faster training but updating the model less frequently. This can sometimes cause over-generalizat...
Rust By Example: Diverging Functions
มุมมอง 2614 วันที่ผ่านมา
In Rust, there are functions called diverging functions that never return. They stop any tasks that start after them, so if you use a diverging function, anything below it won't work. This is known as the never type, which we recognize from an exclamation point used as the return type. Now, you might be wondering, do we always have to use panic with this never function? Interesting question. I ...
Python Double Underscore Dunder Methods and Operator Overloading
มุมมอง 57521 วันที่ผ่านมา
"Magic Methods" 🪄 The Dunder Methods are a type of method used in Python. The term "dunder" stands for "double under," represented by two underscores on either side of the method name. As a Python developer, you've likely used them without even realizing it. An example is the constructor, which you may be familiar with in other programming languages, and in Python it's defined as "double unders...
Vintage Computer Videos
มุมมอง 11921 วันที่ผ่านมา
In the 90s, when you turned on computers, they made all these sounds. The hard drives, disk drives, and floppy disks would spin, and you'd hear clickety and clackety noises. I looked at some of these old machines and found one claimed to be from 2015, but that can't be right. It even mentioned Google and an Android ROM extension, which seems odd for a computer. When I remember the old days, you...
Rust By Example: Match Binding
มุมมอง 27721 วันที่ผ่านมา
What's this "@" symbol all about in Rust programming language? Sometimes its syntax can really confuse us, especially when we're having to dive deep into the code. But don't worry, let's break it down. The "@" symbol is used in something we in Rust call 'binding'. Binding allocates data to a variable, which can be quite a task when dealing with a match statement, for example. But once you get t...
Technology Product Proof Points Checklist for Starting a Business
มุมมอง 104หลายเดือนก่อน
Before starting a business, you should complete a checklist of proof points to boost your chances of success. Begin by answering key questions: who is your market, who is your target audience, will they buy your product, and is it easy to use? For a tech startup, such as one offering an API for AI technologies. Make sure your product meets market needs, identify your primary customer, and analy...
How to Use Kali Linux for Beginners
มุมมอง 242หลายเดือนก่อน
Kali Linux is known for being a top-tier penetration testing distribution. It's designed with a collection of tools that help detect security vulnerabilities in businesses using technology. While any Linux distro can be set up for penetration testing, Kali Linux makes it easy by pre-installing these essential tools, reducing setup time so you can get straight to work. It can run on various devi...
One Million Checkboxes built with Redis WebSockets and Bit Arrays
มุมมอง 381หลายเดือนก่อน
One million checkboxes, that's a lot of checkboxes. And if you think about it, that's only one million bits. In computer terms, that's ones and zeros. When we take photos with our phone, those photos have hundreds of millions of pixels. Each pixel has values from red, green, and blue that add even more data. So one million checkboxes might seem simple. But here's the thing: you can turn each of...
Docker Compose Versioning and Convention Tips
มุมมอง 101หลายเดือนก่อน
Stop versioning your Docker Compose file? Well, it turns out we don't have to do that anymore. When you write your Docker Compose file in YAML, you usually put the version at the top, and we don’t have to do that anymore. That's actually kind of nice, although kind of weird. Usually, these kinds of things are, well, the Docker file itself, the main primary Docker file, whenever you're writing a...
Leetcode Interviews
มุมมอง 99หลายเดือนก่อน
When you go in for an interview for a software engineering role, you'll probably face a LeetCode style interview. LeetCode is a website with common engineering challenges. You don't need to know all the solutions because there's a library for that. LeetCode problems are abstract computer science problems that you solve by writing code. The answer is guaranteed but your method might differ. Thes...
AI Inference vs Training with Machine Learning: How AI Learns
มุมมอง 111หลายเดือนก่อน
AI inference and AI training are processes that work together. Let's look at AI inference first. This is simply asking the AI a question and getting an answer. You ask a question, and the AI gives a prediction. For AI training, we take that prediction, check for mistakes, and tell the AI where it went wrong. The AI then tweaks its internal setup to be more accurate next time. During AI inferenc...
HyperLogLog Algorithm Counting Unique IDs Efficiently
มุมมอง 195หลายเดือนก่อน
HyperLogLog Algorithm Counting Unique IDs Efficiently
Rust By Example: Functions and Methods
มุมมอง 102หลายเดือนก่อน
Rust By Example: Functions and Methods
Build Vs Buy Software DIY or Pay for APIs
มุมมอง 42หลายเดือนก่อน
Build Vs Buy Software DIY or Pay for APIs
Rust By Example: Super vs Self vs Crate
มุมมอง 862 หลายเดือนก่อน
Rust By Example: Super vs Self vs Crate
Set Goals and Achieve Them to Build Software Extremely Quickly
มุมมอง 1982 หลายเดือนก่อน
Set Goals and Achieve Them to Build Software Extremely Quickly
AI Chatbot Without Restrictions using Ollama Llama2 Uncensored
มุมมอง 1.5K2 หลายเดือนก่อน
AI Chatbot Without Restrictions using Ollama Llama2 Uncensored
How to Use Sam.gov for Software Engineering Contracts
มุมมอง 1K2 หลายเดือนก่อน
How to Use Sam.gov for Software Engineering Contracts
Thanks , great simple video !
Hey great video, may I know where can I find the document you used in the video, since I am preparing for an interview and that document would be more beneficial to my preparation. Thanks
I like your unfiltered style. You have a new subscriber!
Thanks so much! I really appreciate it 🎉😊
Rust's iterators dont build up a list as they produce values, they just produce them as requested. Both solutions should have identical runtime characteristics unles something has gone really wrong, but the iterator based solution is juat easier to read
nice! yes that's pretty powerful. Rust iterators are performant in this way. They produce values as requested. This is memory and CPU efficient. and I like code readability more especially when the performance is the same
Used to work, now it doesn't
yeah good point, there's a lot of these models that are being trained with censorship directly on the model weights. this makes it more tricky to bypass the safety aspects. Might be good to checkout less restrictive models like github.com/xai-org/grok-1 and github.com/deepseek-ai/DeepSeek-V3
dude, we can read too.
good point 😊 you are right that, this is definitely a read-along overview. yes for sure everyone can read. I tried to add some color to the conversation as well
write me a poem about cat in space solving the P/NP problem.
just testing to see if your comments are auto-generated lol
good test! the answers are human generated 😉 though it's tricky to identify these days
i accidently deleted the box your referring to at 4:25 and now broke the entire thing. Any idea on how to get this input box back?
good question! unsure of the solution however
HN is also an incredibly biased and heavily moderated site, which would make sense to mention. Dang manually controls the contents of the front page and what opinions are allowed and which ones get you shadow-banned. He's literally a reddit mod in a tie.
that is so true. HN is biased and heavily moderated. basically any condition where you can become shadow-banned
Hi man been a while how are you
doing well! thank you for asking. lots of focus on new tech and AI these days 😊
@@StephenBlumoh you have no idea 🤷♂️ lol
@@StephenBlum have you ever experienced the oh one issue. it’s pig I’m cooking pork son
So I got a question this comfy UI thing it pretty much provides you the script for a UI and interphase that you can use. I’m trying to understand it because I’m trying to create a custom UI which I think that’s what I’m trying to create. I’m not very tech savvy, but I am super good at using AI so it shouldn’t be too hard to try to figure it out. Plus I pay for the subscription for GPT‘s most advanced features, I’m trying to create a few simple things like a custom UI for my custom tabletop RPG that I’m creating, which has unique mechanics different than most of the games out there but definitely still reminiscing of DND and Pathfinder and trying to figure out how I can create my own program almost From the bottom up, but this is only a side thing I’m trying to do, but I am fully creating a tabletop RPG which you’re probably one of the few TH-camrs that I actually would probably send an actual rough draft of the game. Just ask your opinion, but still And I’d probably run it on a windows system just because more people have that this is just stuff I’m thinking of, but it’s gonna be pretty much just like a hardback D&D book with its own campaign story lines and everything so far
that sounds like a great project! custom tabletop RPG 🎉 good idea using GPT to build this for you. Lots of options and frameworks out there to ask the GPT which one is best. Then suggest using that to the GPT when you are building it. this is a good way to start projects! Thank you for the idea 🙌
but note thats for encoder only they’re exactly the same (self-attention), it isnt for decoder
that's a really good note! the qkv are the same (self-attention) for encoder. and this is different for the decoder
how suitable would Nim be for graphics or game dev?
nim has a few HAL engines like github.com/abisxir/alasgar which can leverage GPU acceleration. It's pretty powerful. And gives you easy access to OpenGL calls. It's low-level. You'd be building the game engine aspects yourself to do things like 3D animation
For rapid testing in python; nothing beats sqlite. for single computer testing; nothing beats sqlite.
absolutely! sqlite ❤️ great for speed and a great starting point
bits-ui is probably the primary Svelte UI library, surprised it's not here
good addition! thank you Matt 🎉 bits-ui for Svelte UI 🚀
Great!!!! Thanks
Angular is harder to learn because of the separation of concerns? That's like saying the soup is harder to eat with a spoon than by drinking it directly, though let's see who's messy afterwards. The larger the project (more than a few weeks), the more clarity and separation of concerns are useful, together with dependency injection (battle tested feature in full-power back-ends) Now let's talk about hooks instead if you wanna talk about a steep learning courve.
you make a good point. angular can be easy when you start. Angular and React are both great JS foundations for building applications. React is designed to provide component-level functionality and is considered a JS library. Angular is a full JS framework and it is very powerful. To get the most out of Angular, it's best to learn more about the capabilities
Bro you look like the creepy Cillian Murphy and cillian was creepy looking to begin with
Dude, don't be soo mean!
@johnsmith1953x sorry i had to say that
yes it's a health related reason. i'm working to get better 😊
@@StephenBlum damn you just made me sound like an asshole. Wish you best, take care man and of course thanks for the video
@@nandans2506 it's okay hey don't worry about it! you weren't wrong 😄
I had to use in a few cases over my 7 years of Rust and I absolutely love `@` binding
Hey ◡̈ Thank you for the explanation, is it possible to get a copy of your document? It would be quite helpful for me ◡̈
Yes absolutely here is the link: docs.google.com/document/d/1v9cR3GDPYtEUywMTUn7_uGYXZg5gxEMgMqBpKDOi1_s
is there a filter over your video because its making your face look really really weird
@@koalakakes it's recorded through OBS desktop capture. The colors are slightly different than real life
Where are you from
I live in San Francisco, CA, USA
Aaah the good ol' days.. where I have a lot of friends. Compared to now it's just me and my laptops.
Totally! It was the good ol' days with lots of friends 😄
All of syntax gives me PTSD from when I first learned C++...dark times.
you are right! Rust has syntax on top of even more syntax. It's a lot to learn and it makes it a challenge to even know when to use the various statement operations. I would love a simple-rust similar to Python that makes it easy with the same memory and concurrency safety guarantees 😊
@@StephenBlum Totally agree. Because of this sometimes you feel you're getting nowhere with Rust learning...almost tempting you to switch to another simpler language, like Go!
Rust has almost completed the mission to add every character and slang (yeet, skibdi is next) known to man in its syntax I really do not get how anyone could feel "happy" writing Rust. It is like there is no end to its intricacies. Though, I am circling back to your point: "Can we have a simple Rust?"
yes please! simple rust 🙌 🎉 the language itself has been amazing. We have seen 5-30x improvements each time we replace an existing layer in our stack with Rust. It's performance of C with memory and concurrency saftey make it the greatest language. The only drawback is the syntax is overwhelming. If we can have a simple mode, most applications don't need the advanced yeet's 😊
@@StephenBlum sure, but is this 5-30x improvement comparing Rust to Python? Then it would not be that fair anyway, I have listened to a bunch of your talks and I know your business needs a performance that "C level" languages offer.
@@PouriyaJamshidi yes you are right. the comparison is between Rust and Python, and Rust and Go, and Rust and JVM. We see amazing performance benefits by using Rust. Note that we also use a lot of C already. And we won't see a boost in performance switching our C code bases to Rust.
@@StephenBlum Right, I remember you talked about Go as well in the Rust in production podcast. I would be very interested to know if you ever write something in Nim and how it compares to Rust. We recently wrote a syslog proxy that handles a few hundred thousand logs per day (at times tens of thousands per second) without breaking a sweat. Though, your scale is different
@StephenBlum I wonder why Nim was not considered for the code base.
I might be missing something but I dont believe Q, K and V are identical, if they were they would not be differentiated. Is this a parody of LLM teaching videos ?
Yes good point! The source data needs to attend to itself. So we need copies of the input/output data to compare. That's why the QKV variables are the same. Duplicate data for self-attention so we can multiply the vector with itself to create the attention between each token. Example of translating between English and German: 1- Encoder Self attention Q = K = V = Our source sentence(English) 2- Decoder Self attention Q = K = V = Our target sentence(German) 3- Decoder-Encoder attention Q = Our target sentence(German) K = V = Our source sentence(English)
Again neither the query, key and value vectors are identical nor their weight matrices Q, K and V. The 3 vectors do stem from the same hidden vector h pertinent to the same word, i.e. q = Q.h , k = Kh, v = V.h , but that is it, they are not identical. Is this an experiment/joke or what?
@@yvesbernas1772 Yes you are right. You identified this correctly. This clarification was necessary. Thank you for mentioning this. Yes the three vectors are ultimately different in the way you describe. The problem I ran into early on learning is how they start from the same hidden vector h. This was a huge missing part and it was important that you helped describe this detail. Thank you! 🎉
What about rocket??
Good point! Rocket looks clean. Like a simple and elegant web app server framework. Simplicity is key. And it looks like Rocket does a great job 😄
@StephenBlum yes it does and easier to pick up. My opinion though.
Great video! I’ve been using shadcn-svelte recently and I’m really enjoying it
thank you! that's great to hear. shadcn-svelte is excellent 🙌
What font are you using
`Manaco 15` is the font 😊
A checklist would be phenomenal! This is great stuff!
Good idea! Here is the checklist direct from the video: docs.google.com/document/d/1I_9e0kESyWCcoqiLfdCfjctvul7RaO0DLpLx-ynnlY0/edit?usp=sharing
Do you have a link to this checklist? Would love this
Yes absolutely. Here is the checklist from the video: docs.google.com/document/d/1I_9e0kESyWCcoqiLfdCfjctvul7RaO0DLpLx-ynnlY0/edit?usp=sharing
@@StephenBlum Thank you!!!!
I am currently using react in my company portfolio website and I think it is pretty slow and heavy for just rendering some shadcn components and framer-motion and static data. I have rarely used useState too, let alone other hooks like useeffects, reducer, memo and callbacks. But I don't think this is for me, since the syntax are basically different and I would be converting like entire code manually. Last time I checked, there were at least 20 components and 10 pages. not gonna transfer.
Yes you are right. ReactJS is very slow. Preact can help speed it up. And if you use the preact-compat library, most components should work github.com/preactjs/preact/blob/main/compat/package.json
Great explanation and video! Everything is great, except that the meaning of row and column in the Q/K/V matrices might be switched, Am I right? is Q dot t(K) a token-by-token matrix?
Good point! Q dot t(K) is the token by token matrix. Each token is a vector, commonly 512 floats per token. Both Q and K are the same array of tokens
How do I customize Kali Linux for specific penetration testing tasks?
Kali Linux comes installed ( or offers easy access ) to all pentest tools. For specific pentesting, you just need to create a list of your favorite pentest tasks. A great way to get a list of ideal tools available, most of the LLMs can provide a list that matches your specific tasks 🎉
@@StephenBlum thanks for ur advise
thanks for the video. How about good easy ways to create the textured look and export it to web ready format? say from Illustrator or others?
Great suggestion. Illustrator can export directly to web-ready SVG. And you can use that SVG to make fantastic textures 🎉 just save/export the file to SVG. If there is an optimization option for web export, make sure to select that option so the file is smaller
I need Million polygons on flutter map with onclick and state How can I make it work fast?
good question! for "fast" with a million polygons, you have to do it progressively. If you are looking to draw all polygons on the screen at the same time, then it might be a non-starter. If you are only showing some of the polygons on the screen, then using most 3D render frameworks will automatically take care of this for you by only drawing the visible polygons in the viewport. 3D frameworks automatically cull. Here are some types of culling: Back-face culling: A technique that avoids drawing polygons that are facing away from the camera. A polygon's vertices have a clockwise winding if you're looking at the back face, and a counter-clockwise winding if you're looking at the front face. View-frustum culling: A visibility culling technique. Occlusion culling: A visibility culling technique.
@ so it meant to show it effectively - don’t show what is not visible at moment? I had in idea for example to have 20 layers for 20 zoom levels and cluster polygons when zoom out , and when zoom in hide what’s not visible in the area. Something like that
@ by the way, happy New Year! Very nice channel
@@sergannn thank you! happy New Year! 🎉
@@sergannn that's a great idea! that would dramatically improve performance. Multiple LOD level-of-detail layers/zooms so that when the camera is zoomed out, a simple model with fewer polygons is drawn instead of the full 1m polygon model
thanks dude
you're welcome! 👍😄
Most of the software that needs to be built, has already been built. At this point we may tweak things here and there, but any further innovation will provide only marginal improvements.
that's actually a really good point! as of today, most of the software we need has already been built and it works mostly well. we can make improvements and fixes. other then that, it's already been written
Hey Stephen, Thank you so much for reacting to/explaining my blog. It was an awesome video!
great to hear you say the video was helpful, your blog is really well written 🎉😄 your blog helped me out a lot thank you!
@@StephenBlumThank you
Great video! Loved that all my C++ knowledge is still relevant lol
@@siddharthmanumusic thank you! 😄 Yes absolutely you are right. C++ is relevant and heavily used in advanced AI frameworks
Thanks man.
No problem! glad you found the video 😀
Thanks for info !!
Any time 😊 thank you!
Sadly it's heavily censored making it useless, it's nightmare to tweaking it.
agreed, the Gemma models and Google AI models are heavily censored for safety. This can become a problem even for seemingly simple tasks, the AI will guard it's answers
What's the font family name used @1:10 ?
`Monaco 15` is the font family. running on a Mac terminal emulator window
@@StephenBlum thank you
A big part of it is interest rates though. here is the reason: When investors have cheap money, large green projects can start which requires a lot of software development. However, when money is expensive, companies and investors typically stop those types of project and just focus on their bread and butter which churn out profits. Those types of projects usually require much less software developers to maintain. That is the short of it, more or less.
you're right, that's an important perspective on interest rates. with cheap money, large green (new) projects start with lots of software development. Without cheap money, companies stop making new projects
About how much did that ec2 instance cost for the time used to create this video?
Smart question! you figured it out. Yes processing videos on servers is smart that you figured this out. AWS charges for each second the EC2 instance is turned on. The time is about 2-3 minutes per video ( about $0.50 per video ~ )
Cool Thx!
Beautifully explained
I appreciate that! I put a lot of effort into creating this video 🎉
@@StephenBlum you have really good content. If you use canva or Microsoft designer for video cover. Makes them more clickable. And call to action in your videos to subscribe. Love your content. Should be hitting 50k subs with a few tweaks. Especially on topics like pandas, ML and LLMs
you have good video tips! this is helpful thank you! 😊
this is cool but how can I do this but outside my network as well? I have a AI server running Zorin with Ollama but when im not at home I want to use these big models with out using the resources of my current machine or device using enchanted. all of my other devices are MacOS. I looked at ngrok but they time out after 8 hrs it looks like and I wouldn't mind paying for it if I there wasn't a cap on it.
one option to get 100% up and running with your at-home GPU and remote access is to use PubNub.com API to send/receive the text data. it does take some setup and coding. you can create a chat app interface that delivers the prompt to your GPU running the model, and then publishes the response back. user app -> PubNub Publish API user prompt -> your server subscribes to the events and submits the prompt to the GPU model -> your server publishes back the answer to -> user app is subscribed to the response channel and receives the answer. Copy and paste the description above into an AI tool to build the app for you 🚀
A couple comments. The article reads a lot like "Man selling shovels says the gold rush is real". I feel like there is a lot of confusion behind what developpers do. At this point if AI tools are significantly accelerating your workflow. I have lots of questions about what you do. I find it most helpful working at the edge of what I usually do. The places where I know there is a library doimg it and I have a sense of how it works. But I'll need a lot of googling to get things started and get then quite right. In the things I do regularly, it's at best a typing assistant. In the things I don't understand how they work. You won't get much further than hello world style things because you don't understand it enougj to fix it when it does nonsense.
you make a strong point. the AI is just a tool. let's imagine for a second that there is an AI tool that creates perfect code. You still need a human software engineer to direct it because there's scenarios like you describe where the software needs to be maintained. The tool needs guidance
Where's the tutorial? Discussing about a tool is called a tutorial now? Nice video but wrong title.
you are right, the title is wrong because it's mostly a discussions video and a mini getting-started intro with a code walkthrough. that doesn't really count as a tutorial in this case, more like it's an overview
@@StephenBlum more like it's a clickbait.
@@true_visual good point. the video is more of an overview with some code reading of the tutorial. It's more of a video reading the public tutorial rather than me creating one from scratch
@@StephenBlum So why didn't you name it "Elysia JS Overview"? You waste other people's time by putting a false title for engagement.
@@true_visual good idea. I'll update this now.
I work in AI development for bank. And I started to use gpt for coding help just because managers nowadays are so obsessed with this thing and you have a lot of simultaneous project that you cannot cope without using helpers such as code copilots just to speed up your work.
the managers think that it saves more time than it actually does. there is a lot of hype. the GPT tools do help a bit. it's great that it saves some time we using AI tools. It allows us to focus on the more creative parts of our work