1作者: cristinon7 个月前原帖
我正在建立一个小型的生产力同行小组,专为那些真正使用生产力系统来保持专注并实现目标的人士而设。这不是针对那些仅在YouTube上看过一段关于Notion视频的人,或是对生产力有随意兴趣的人,而是为那些已经在跟踪自己工作(如创业、学习、编程等)并希望与几位同行分享进展、工作流程和反馈的人士准备的。 这个小组不涉及任何盈利、个人宣传,也不允许“辅导”,因为这会破坏自由分享知识的动机。 这也不是一个有成千上万不活跃且不贡献的人的“社区”,而是一个小型的个人“群体”,就像一个群聊。因此,成员人数将限制在10人。 我们将做的一些事情包括: - 分享每周目标、进展和反思 - 比较系统/工具(如Obsidian、自定义设置等) - 提供高质量的建议和反馈 如果你是那种: - 已经在使用某种系统(如每日回顾、每周计划、第二大脑等) - 正在朝着某个重大目标努力(如创业、深度学习、长期目标) - 重视反馈和真实的责任感而非内容 请填写这个简短的申请表: https://form.typeform.com/to/uVz3sGPI 欢迎在评论中提问。
1作者: renovate51417 个月前原帖
我在这里代表我的朋友发布信息,我觉得这个工具非常实用,所以想和大家分享一下。 大家好,HN(黑客新闻)! 我开发了 gtime,这是一个 Python 命令行工具,用于查找、比较和转换全球城市的时间。它支持模糊搜索、收藏夹、会议时间转换和实时监控模式——所有这些都通过 Rich 库提供丰富多彩的终端输出。 创建这个工具是因为现有的命令行选项感觉太有限或笨重。gtime 旨在让处理全球时间变得快速而愉快,特别适合远程团队或频繁安排日程的人。 试试吧: ```bash $ pip install gtime ``` GitHub: [https://github.com/savitojs/gtime](https://github.com/savitojs/gtime) 欢迎反馈、功能请求和问题!
7作者: sincethebbsera7 个月前原帖
以下是来自一位自从使用Lotus 123、WordPerfect和QBasic以来一直坐在电脑屏幕后的人给出的诚恳反馈。 首先,选择一个方向并坚持下去。你在聊天中,向下滚动以查看最近的消息。你试图在无尽的软件集成驱动的信息海洋中找到一条私信,于是你点击“最近的私信”,自然开始向下滚动——但不,你得向上滚动才能看到这里的新消息。 于是你找到了一个你认为一直在寻找的消息,但现在你又得向下滚动一次,才能看到更近期的消息,而且速度非常慢。 等待这个慢吞吞的应用程序重新加载你第一次错误滚动的每一条消息,而现在你得朝着“正确”的方向回到你最开始的位置。 你能直接按Control+End吗?或者点击那个箭头期待它能跳到最后一条消息?当然不行。你只能继续滚动,每次加载一页,痛苦不堪,因为你面临的是一个“懒加载器”——更准确地说,是懒惰开发的结果。 这一切为什么会发生?因为你根本找不到你想要的东西。能够摆脱这3,000个完全无用的软件集成中出现的“机器人”聊天会很好。谁需要从Excel或屏幕截图应用中接收消息?这只是为了集成而集成——其中大约2,500个毫无附加价值。 这一切都是噪音。 无用的噪音,现在在我电脑上占据了超过一GB的空间,以支持这一切,同时消耗着CPU资源和我的电费,伴随着一层层思路不清的系统开销,支持那些我现在不需要,也永远不打算使用的应用程序。 在我看来,这根本不值得去修复。它从根本上是坏的,采用了应用开发中的最差实践。 是时候重新思考并重新开始了。 谦恭地,
3作者: EGreg7 个月前原帖
有一个函数可以异步从某个地方获取一些值吗?考虑将其封装在这个函数中,使其成为一个超级函数。 以下是它为所有被封装的函数所做的事情。在我的经验中,这些功能非常有用,并且为您提供了一个可以进一步扩展的地方(例如,透明地处理批量请求等): - **记忆化异步获取器**:使用相同的参数调用函数时,它会返回缓存的结果,而不是重新计算。 - **处理进行中的去重**:如果应用的多个部分在同一时间调用相同的获取器,而它仍在工作中,则只会发送一个请求。其余的请求将等待同一个 Promise。 - **限制并发**:您可以限制同时运行的获取器调用数量。这对于 API、磁盘 I/O 或任何速率敏感的操作非常有用。 - **支持自定义缓存后端**:传入任何具有 get、set、delete 和 has 方法的对象。可以与 Map、LRU 或您自己的缓存逻辑一起使用。 - **可选的 LRU 驱逐**:如果您传入一个普通的 Map,它会将其升级为具有最大大小的 LRU。当缓存满时,最少使用的项目将被驱逐。 - **处理回调和 Promise**:封装传统的回调式异步函数,但提供现代的基于 Promise 的接口。 - **智能键生成**:通过将非函数参数字符串化来构建缓存键。对于大多数日常用例效果良好。 - **支持手动驱逐**:调用 getter.forget(...args) 来移除特定条目,或调用 getter.force(...args) 来绕过缓存进行一次调用。 - **允许自定义准备逻辑**:您可以传入一个 prepare() 函数,在使用缓存结果之前对其进行克隆或处理。 ```javascript function createGetter(fn, { cache = new Map(), cacheSize = 100, // 仅在缓存为 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; } ```