1作者: cristinon6 个月前
我正在为那些真正使用生产力系统来保持专注并实现目标的人建立一个小型生产力互助小组。这不适合那些仅仅在 YouTube 上看过一个关于 Notion 视频的人,或者只是随便感兴趣的人,而是为那些已经跟踪自己的工作(创业、学习、编码等)并希望与几个同伴分享进展、工作流程和反馈的人准备的。<p>不允许任何形式的盈利、自我推销或“指导”。这会破坏自由分享知识的动力。<p>这也不是一个拥有成千上万不活跃且不贡献成员的“社区”,而是一个小型个人“小组”,就像一个群聊。因此,它将限制在 10 名成员以内。<p>我们会做的一些事情: - 分享每周目标、进展和反思 - 比较系统/工具(Obsidian、自定义设置等) - 提供高质量的建议和反馈<p>如果你是这样的人: - 已经在使用一个系统(每日回顾、每周计划、第二大脑,或其他任何系统) - 正在为一些大事而努力(创业、深度学习、长期目标) - 重视反馈和真正的问责制,而不是内容<p>请填写这份简短的申请表: https://form.typeform.com/to/uVz3sGPI<p>乐于在评论区回答问题。
1作者: renovate51416 个月前
代朋友发帖,我来宣传一下,觉得挺好用的,所以想和大家分享一下! Hi HN! 我开发了 gtime,一个 Python 命令行工具,用于查询、比较和转换全球城市的时间。它支持模糊搜索、收藏夹、会议时间转换,以及实时/观察模式——所有这些都通过 Rich 库在终端上呈现彩色输出。 开发这个工具是因为现有的命令行选项感觉太受限或笨拙。gtime 旨在让处理全球时间变得快速而愉快,特别是对于远程团队或经常安排会议的人来说。 试用一下: $ pip install gtime GitHub: <a href="https://github.com/savitojs/gtime">https://github.com/savitojs/gtime</a> 欢迎提供反馈、功能请求和问题!
7作者: sincethebbsera6 个月前
以下是一位从 Lotus 123、WordPerfect 和 QBasic 时代就开始使用电脑的人的诚实反馈。 首先,选定一个方向并坚持下去。你在一个聊天界面里,向下滚动查看最近的项目。你想在一个充斥着软件集成信息的无尽海洋中找到私信,于是你进入“最近的私信”界面,很自然地开始向下滚动——但不对,在这里你需要向上滚动才能看到新消息。 然后你找到了你认为一直在找的那条私信,但现在你又不得不再次向下滚动才能看到更近的消息,而且速度非常慢。 你得等着这个缓慢的应用程序重新加载每一条消息,而你之前错误地滚动了一次,现在却要朝着“正确”的方向滚动,才能回到你开始的地方。 你难道不能直接按 Ctrl+End 键吗?或者点击那个箭头,期望它能直接跳到最后吗?当然不行。你只能继续滚动,因为它正在加载,而且痛苦地一次加载一页,因为你遇到了“懒加载”——这实际上是懒惰开发的结果。 这一切都是为什么?因为你一开始就找不到你想要的东西。如果能摆脱这些来自 3000 个绝对无用的软件集成的“机器人”聊天就好了。谁需要从 Excel 或屏幕截图应用程序那里接收消息?这只是为了集成而集成——其中可能有 2500 个集成根本没有增加任何价值。 这全都是噪音。 这些无用的噪音在第一天就占据了我电脑上超过 1GB 的空间来支持这一切,同时还消耗着 CPU 周期和我的电费,而这些都是为了支持我既不了解,也从未打算使用的应用程序,而这些应用程序又需要不断地打补丁,并且系统开销考虑不周。 我个人认为,这甚至不值得尝试修复。它从根本上就是坏的,并且是使用最糟糕的应用程序开发方法构建的。 是时候重新思考并重新开始了。 谨上
3作者: EGreg6 个月前
你有一个函数,它从某个地方异步获取一些值?考虑用这个函数来包装它,并使它成为一个超级函数。<p>以下是它对你用它包装的所有函数所做的事情。根据我的经验,这些都非常有帮助,并且还为你提供了一个可以嵌入并稍后添加更多功能的地方(例如,透明地处理批处理等):<p>记忆化异步获取器:使用相同的参数调用一个函数,它会返回缓存的结果,而不是重新计算。<p>处理正在进行的去重:如果应用程序的多个部分在获取器仍在工作时调用相同的获取器,则只发送一个请求。其余的等待同一个 Promise。<p>限制并发:你可以限制对获取器的调用并行运行的数量。这对于 API、磁盘 I/O 或任何对速率敏感的东西都很有用。<p>支持自定义缓存后端:传递任何具有 get、set、delete 和 has 的对象。适用于 Map、LRU 或你自己的缓存逻辑。<p>可选的 LRU 驱逐:如果你传递一个普通的 Map,它会将其升级为具有最大大小的 LRU。当已满时,将驱逐最近最少使用的项目。<p>处理回调和 Promise:包装传统的回调式异步函数,但为你提供一个现代的基于 Promise 的接口。<p>智能键控:通过字符串化非函数参数来构建缓存键。适用于大多数日常用例。<p>支持手动驱逐:调用 getter.forget(...args) 以删除特定条目,或调用 getter.force(...args) 以绕过一次调用的缓存。<p>允许自定义准备逻辑:你可以传递一个 prepare() 函数来克隆或处理缓存的结果,然后再使用它们。<p><pre><code> function createGetter(fn, { cache = new Map(), cacheSize = 100, // 仅在 cache 是 Map 时使用 throttleSize = Infinity, prepare, callbackIndex, resolveWithFirstArgument = false } = {}) { const inFlight = new Map(); let activeCount = 0; const queue = []; // 如果需要,将 Map 包装在一个简单的 LRU 中 if (cache instanceof Map) { const rawMap = cache; const lru = new Map(); cache = { get(key) { if (!rawMap.has(key)) return undefined; const value = rawMap.get(key); lru.delete(key); lru.set(key, true); // 标记为最近使用 return value; }, set(key, value) { rawMap.set(key, value); lru.set(key, true); if (rawMap.size > cacheSize) { const oldest = lru.keys().next().value; rawMap.delete(oldest); lru.delete(oldest); } }, delete(key) { rawMap.delete(key); lru.delete(key); }, has(key) { return rawMap.has(key); } }; } function makeKey(args) { return JSON.stringify(args.map(arg => (typeof arg === 'function' ? 'ƒ' : arg))); } function execute(context, args, key, resolve, reject) { const callback = (err, result) => { if (err) return reject(err); cache.set(key, [context, arguments]); if (prepare) prepare.call(null, context, arguments); resolve(resolveWithFirstArgument && context !== undefined ? context : result); processNext(); }; if (callbackIndex != null) args.splice(callbackIndex, 0, callback); else args.push(callback); if (fn.apply(context, args) === false) { cache.delete(key); // 选择不使用缓存 } } function processNext() { activeCount--; if (queue.length && activeCount < throttleSize) { const next = queue.shift(); activeCount++; execute(...next); } } const getter = function (...args) { return new Promise((resolve, reject) => { const context = this; const key = makeKey(args); if (cache.has(key)) { const [cachedContext, cachedArgs] = cache.get(key); if (prepare) prepare.call(null, cachedContext, cachedArgs); return resolve(resolveWithFirstArgument && cachedContext !== undefined ? cachedContext : cachedArgs[1]); } if (inFlight.has(key)) { return inFlight.get(key).then(resolve, reject); } const promise = new Promise((res, rej) => { if (activeCount < throttleSize) { activeCount++; execute(context, args.slice(), key, res, rej); } else { queue.push([context, args.slice(), key, res, rej]); } }); inFlight.set(key, promise); promise.finally(() => { inFlight.delete(key); }); promise.then(resolve, reject); }); }; getter.forget = (...args) => { const key = makeKey(args); inFlight.delete(key); return cache.delete(key); }; getter.force = function (...args) { getter.forget(...args); return getter.apply(this, args); }; return getter; }</code></pre>