V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX  ›  secondwtq  ›  全部回复第 79 页 / 共 123 页
回复总数  2453
1 ... 75  76  77  78  79  80  81  82  83  84 ... 123  
2019-09-30 19:48:22 +08:00
回复了 hzb 创建的主题 问与答 上海 一个人 国庆 怎么过
当然是加班啊,为全面建成小康社会做贡献
2019-09-30 01:50:28 +08:00
回复了 glogo 创建的主题 程序员 有什么高质量的国外技术博客可以订阅?
2019-09-30 00:45:38 +08:00
回复了 glogo 创建的主题 程序员 有什么高质量的国外技术博客可以订阅?
@zhuangzhuang1988 第一个想到 Eli Bendersky ... 结果发现被人说了←_←
2019-09-29 22:33:54 +08:00
回复了 shijingshijing 创建的主题 程序员 没人聊聊 [送给最好的 TA.apk] 这个整蛊 apk 么?
没必要吹 iOS,Android 要是有一个调节音量的权限,默认不开,就都解决了

问题是无论 iOS 还是 Android 都是为傻逼设计的,厂商考虑到(自己认为)用户是傻逼就不会做这种基础的事情
自食其果
2019-09-29 00:09:09 +08:00
回复了 razios 创建的主题 随想 现在的手机都太笨重了
@janus77 所以低端机有小的么 ...
某果现在可是小机器比大机器卖的贵
2019-09-28 23:56:09 +08:00
回复了 amiwrong123 创建的主题 程序员 Java 泛型方法与通配符 其中的类型推断该如何理解?
@secondwtq s/假设 X 是 Object,然后我们的 // ...
2019-09-28 23:51:11 +08:00
回复了 amiwrong123 创建的主题 程序员 Java 泛型方法与通配符 其中的类型推断该如何理解?
@amiwrong123
我也是最近也开始研究 subtyping,我发现一个规律是 covariance 和 contravariance 一般是对称的,这个问题可以从这个角度出发理解:
Holder<?>,这里的 ? 可能是任何类型 X

在 T wildSubtype(Holder<? extends T> holder, T arg) 中,可以直接把 T 推断为 Object,注意 Object 是 Top Type,是任何类型的 supertype (包括它自己),X <: T 这个 constraint 对任意 Holder<X> 都成立,X 既可以是 Integer,也可以是 InternalFrameInternalFrameTitlePaneInternalFrameTitlePaneMaximizeButtonWindowNotFocusedState

在 T void wildSupertype(Holder<? super T> holder, T arg) 中,没有合适的 ?:
假设 X 是 Object,然后我们的 constraint 是 T <: X,然后既然 X 是任意的类型,那么这个 T 应该直接推断成 Bottom Type,也就是 null,所以 wildSupertype(unbounded, null) 是可以过编译的
但是你给的 lng,无论把 T 推断成 Long/Number/Object 等等都是错的,比如 T 是 Object,那么 X 就只能是 Object,T 是 Long,那 X 就只能是 Long/Number/Object/Serializable ... 无论哪种情况,如果 我的 Holder<?> 实际上是一个 Holder<HasThisTypePatternTriedToSneakInSomeGenericOrParameterizedTypePatternMatchingStuffAnywhereVisitor>,T <: X 就不成立了
很纳闷不用 FCPX 的话为啥要用白苹果剪视频 ...
2019-09-28 13:59:40 +08:00
回复了 BruceAuyeung 创建的主题 程序员 c++动态调用链接库的问题
首先楼主这个问题和 C++ 没关系,其实应该算是 Linker/Loader/ABI 的范畴,传统上算是 C (”学会 C 语言“在现在的语境下已经包含了太多的东西了)。

可以把原问题大致分成两个部分:
第一是定位并载入动态库以及库中的符号,这一步完成之后会给你一个函数代码的指针。而楼主是要运行时动态加载一个库,这个也是没有问题的,OS 提供了相关的 API,很多软件都有类似插件系统一样的东西,最常见的就是各大主流操作系统都支持的驱动和内核扩展——实在不行你自己定义一个格式自己载入也行 ... 做 JIT 都会涉及类似的操作,至于直接载入 native code 的也有,我猜 Chrome 之前搞得什么 NaCl 就是。
只不过现在都去写 JavaScript,扩展需求一般直接写程序解决不编译成 binary (这实际上是更好的方式),才会有楼主的问题——但是讽刺的是,node 里载入 native 库本来就会走同样的一个流程,并且 node 生态是很依赖 native 库的。

(另外用 binary 做扩展还是写代码做扩展,其实更多取决于需求,Solaris DTrace 和 Linux eBPF 这些做 profiling 的工具虽然是内核级的,但都是用户写程序运行时编译然后塞进内核里面跑,甚至可以直接 JIT 成 native code,像 bcc 一类的工具实际上把 eBPF 做成了 kernel 的 WebAssembly,这对于剖析程序行为过程中不断的调试是很有帮助的。做 graphics 的话,调试过程中 shader 都是一个文本塞进去 JIT 的,而且 GPU 并没有统一的 ISA (不仅仅是不同 vendor 之间的区别,同一 vendor 的不同代产品也不一样),不好直接跑 native code。而使用 native code 做扩展,好处是不限语言,性能上限一般更好(虽然会失去做 IPO/PGO 的机会),并且更方便扩展本身代码的保护。
至于 JavaScript 为啥不兴搞 native 扩展,纯属是因为确实需要做 native 扩展的需求太少,就算有点需求,对于大多数人来说做 native 扩展的成本又太高)

第二步是(在上一步已经得到函数指针的情况下)调用对应的函数。这个就涉及到 Data Layout 和 Calling Convention 之类的问题。

需要注意这两步之间的区别,尤其在外部库和程序本身使用同一种语言的情况下,”动态加载动态库“和”动态获取并调用其中的*任意*函数“是两个过程,在讨论实现细节时把它们混在一起说是不合适的。一般使用 C/C++ 作为 host 来实现的插件系统,都是由 host 来寻找并载入一个动态库,之后会固定地调用其中的某个 init 函数(函数名称、签名都是固定的),init 函数再把各种扩展的东西注册到 host 中。这个过程中所有的接口都是 host 早就决定好的,因此不涉及”动态获取并调用其中的*任意*函数“的过程。

为了更好的理解第一步和第二步之间的区别,首先应该理解“一个编程语言调用自己写的库”和“一个编程语言调用 C 写的库”之间的区别。
很多编程语言都有自己钦定的调用(同样是该编程语言写的)外部库的方式——所有那些乱七八糟的模块,包,import 都属于这个范畴。但是它们的共性是都是调用自己写的东西,你在 Java 里面 import 一个包进来,那个包是 JVM Bytecode 格式,你在 Python 里面 import 一个模块,那模块也是 Python 写的。因为是同一个编程语言,同一个编译器实现,所以你能直接用语言原生的方式使用外部库,非常自然,一般这都是最方便的方式。
但是这是静态调用,如果要动态调用外部库,一般需要其他方式。典型的在 Java 里,动态载入 class 需要用反射。(对于解释型语言来说,静态调用和动态调用是有可能统一的,比如 JavaScript 的 require 就是万能的,既可以静态调用也可以动态调用)。不变的是依然需要所调用的模块是使用该语言编写的——这个说法不严格,应该说是符合该语言自身体系标准的,比如在 node 里可以用 require 来调用 native addon,但是这要求 addon 文件自身实现了 addon 的接口,你不能直接编译一个 OpenSSL,然后就在 node 里把它的 .so require 进来,这个需要使用下一种方式。

这里就可以看出来,无论是静态调用和动态调用,你都会使用一种机制来找到对应的库,在库载入进来之后,使用库中函数的过程,就和使用你自己用该语言写的函数是一样的。“找库”和“调函数”是两个正交的东西。

下一种方式,就是在某个编程语言里面调用 C 外部库。
一个编程语言可以不实现任何的模块等调用外部库的方式,却依然是图灵完全的。但是这样的编程语言字啊实际场景中最多只能做到 Hello World,难以回答“JavaScript 也可以写服务器么?”这种问题。所以编程语言要做模块,做包,也即上面所说的“调用同样是该编程语言写的外部库”的机制,并且提供一堆的库,现在你提供了库让 JavaScript 可以写服务器了,但是缺乏常识的萌新们又问出一堆问题:JavaScript 可以写桌面程序么?可以做 IoT 么?可以做韩国女团的人脸识别么?
解决这些问题的终极方案,就是实现一个调用 C 外部库的机制。因为如果一个编程语言能调用 C 库,实际上就相当于 C 有的库它都能有。这样 JavaScript 就不仅能做韩国女团的人脸识别,甚至还能控制火箭发射(以及火箭爆炸),你就直接告诉萌新们“C 能做的我都能做”就可以了。所以任何一个像样的语言,都会有一个调用 C 库的机制。
这个“调用 C 库的机制”也分不同的方式,常见的一种是:用 C 写 binding,和你要调用的库链接到一起,这一般需要依赖于语言实现的具体 API (在 Java 里倒是有标准化的 JNI,但是我觉得不是所有人都把 JNI 当作是自己认知中“Java 语言”这一概念神圣不可分割的一部分)。Python 和 Lua 的 C Binding、Node 的 C++ Binding 都是一个道理。
还有一种是使用语言本身来描述 C 接口,开发者不需要写任何 C 代码。这个可以继续细分,不过区别更加微妙——一些编译型语言可以在编译时静态生成对 C 函数的调用,比如 Go 的 cgo 和 Haskell 的 FFI。编译型语言也可以在运行时进行完全动态的调用,比如 OCaml 的 ctypes。而解释型语言由于没有这个区分,所以这个做得都差不多,典型如 Python 的 cffi,LuaJIT 的 FFI。
(从命名可见,狭义上的 FFI 仅仅指上面最后一段的东西 ...)

在这种场景下,你依然可以选择是“调用其中固定的函数”还是“动态调用任意函数”,对于编译型语言,你还可以选择“编译时链接固定的库”还是“运行时动态载入库”。

这里有两个常见的特例:
一个是 C,对于 C 来说,不存在“调用自己写的库”和“调用 C 写的库”的区别(因为”自己 = C“ ...)。这样所有其他编程语言费了半天功夫实现的编译器接口也好 FFI 接口也好,在 C 里都是 free 的,因为所有 C 库都天然地符合 C 自身的体系,根本不”foreign“。
但是标准 C 仅仅解决了”静态调用外部库“的问题,并没有解决”动态调用“( C 标准根本就和动态库都没关系)。这个就需要用操作系统的动态库 API,结合 libffi。由于 C 的表达能力实在太过捉鸡,所以这个写起来就像在写另外一种语言,尽管调的还是 C 函数。
在这个过程中,操作系统 API 解决的是”动态加载动态库“的问题,libffi 解决的是“动态调用函数的问题”。实际上没人拦着在 c 文件里面写一个函数,然后在同一个 c 文件里面用 libffi 调用它。

另一个是 C++,首先 C++ 与 C 保持了很大的兼容性,也能直接调用 C 库(嘛虽然有个 extern "C"),这样上面说 C 的话,对 C++ 也都成立。C++ 标准也没解决动态调用的问题,所以动态调用 C 库也需要 libffi,但是问题在于动态载入 C++ 库(这个没问题),*并且*动态调用其中的函数 ... 因为
我至今没见过有人做过那么疯狂的事情!
虽然说有无数的语言都不断地打磨自己的 C FFI,但是很少有做“C++ FFI”并且实质上成功的。尽管 C++ 的生态也很丰富,支持调用 C++ 库中的内容(哪怕是个 binding )的好处也很大。
这不仅仅是 C++ 复杂性的问题,很大程度上也是因为 C 实在太过 primitive,几乎相当于所有语言的下限,而 C++ 接口中涉及的概念对于很多编程语言来说就是根本不兼容的(很多语言没有 class ),所以做“C++ FFI”这个事情,很多时候 by definition 就是有问题的(就不说 template 根本没法做)。
所以很多 C++ 库都是库本身用 C++ 写,然后用 C wrap 一下接口,这样所有能调用 C 的语言,也都能调用这个库。
这就是为什么说楼主的问题和 C++ 根本就没有关系。
话又说回来,这里”动态加载 C++ 动态库“其实是没有问题的,问题出在“调用 C++ 动态库中的函数”这一步。

当然上面这些都是上个时代的东西,现在 114 天就可以产生 514 个新的 RPC 框架,而在 polyglot 的世界里,很多 RPC 框架是跨语言的。跨语言的 RPC 框架一般试图提取各种语言数据模型的共性(即:各种语言的下限,或最大公约数),并且使用一个语言无关的 IDL 来描述。比如 COM/DCOM ( literally 也是上个时代的东西 ...)就是使用一个微软扩展过的 IDL,gRPC 使用 Protocol Buffer 等。
IDL 不仅仅 RPC 会用,它可以作为一个抽象层存在于任何跨语言的场景中(只不过现在萌新们只知道 RPC ...)。比如 DOM API 就是语言无关的,DOM API 可以用一种叫 WebIDL 的东西来描述。而浏览器引擎一般都会带这样一份 IDL 定义,然后会实现一个代码生成器,在编译时根据 IDL 生成对应 JavaScript 引擎的 binding,将引擎中的 C++ 接口暴露给 Web 开发者。这个原理和写 node C++ addon 其实是一样的,不过流程要成熟许多,更方便维护。
所以楼主说用 XML 也好 JSON 也罢来描述接口,多少也有点重新造轮子的意思。

@Shazoo 你 assume 了所有代码都是自己控制的,忽略了第三方扩展的需求。并且写 bridge library 并不一定比 FFI 更方便。
很多时候 bridge 需要依赖于编译器的 API,这是编译器的一个实现细节,原则上用户不需要关心。
更别说某些语言的 FFI 只需要一个 C header 就可以帮你把很多事情全做掉,方便的 FFI 恰恰是语言和生态强大的体现,必须写 bridge library,反倒是个问题。
2019-09-28 11:11:55 +08:00
回复了 anhkgg 创建的主题 程序员 教会微信:突破文件发送 100M 限制
楼主这跟微信杠了多久了 ... 都做了个教会专用的版本了
2019-09-28 01:50:11 +08:00
回复了 cskeleton 创建的主题 分享发现 终于找到经常网址复制不全的原因了
@jasonyang9 如果真的是 MS 的人,那么他们强奸一次用户,就会在注册表里面加一个选项能让你回退掉 :)
2019-09-26 21:24:59 +08:00
回复了 taogen 创建的主题 程序员 你们读过计算机四大名著吗?
@scukmh 贵校教 CLRS ?
2019-09-26 21:15:22 +08:00
回复了 ChristopherWu 创建的主题 程序员 看 SICP 不如先看 The Little Schemer
The Little 其实是一个系列,用不上 Scheme 也可以看看别的:
The Little LISPer
The Little MLer
The Little Schemer
The Seasoned Schemer
The Reasoned Schemer
A Little Java, A Few Patterns
The Little Typer
The Little Prover
2019-09-26 21:11:45 +08:00
回复了 jeblur 创建的主题 问与答 想搞一个 manjaro,问题来了
先搞个虚拟机试试吧
桌面 Linux 没有“优秀”的 distro
2019-09-24 01:37:59 +08:00
回复了 mpb 创建的主题 职场话题 校招想进大厂真的好玄学啊,心态都不好了
运气确实很重要。你仔细想想就会发现人生从头到尾都 tm 靠的是运气,所以没必要揪着这一件事折腾。
2019-09-24 01:25:24 +08:00
回复了 PainAndLove 创建的主题 程序员 敲代码的另一种方式?
“键盘+定位设备”这种配器模式有它适用的地方,只不过不是”敲”代码。
普通用户一般会认为有 GUI 的地方就离不了某种定位设备,可能是鼠标、触摸板、触摸,或者手写笔。
程序员知道 Vim,知道 text-based interface,快捷键玩的也溜,但是程序员的问题就在于一般只跟代码和文档打交道,所以楼主尽管有跳出圈子的想法,但是也局限在“敲代码”的边界里面 ...
但是同时不少程序员也玩游戏,玩摄影,做视频,绘画,在进行这些活动的时候,定位设备依然是不可或缺的。可惜的是,这四种活动中你的操作基本是完全随机的 ... 只有做视频跟编程沾边比较多

楼主可以了解下 Visual Programming,在这种形式里面,开发者主要做的不是写代码,而是拼接已有的逻辑和模块。这种方法本质上依赖于 GUI,并且也很大依赖于定位设备。所以之前那些编辑器什么的不管用,一个基本的“IDE”是最低要求。并且如果要做的好用,需要你发挥一点交互功力(再不济也得发挥点抄袭功力)来真正提高这个 IDE 的效率。

举个例子:写一个函数,你得先把签名定下来,参数名和类型写上去,写到一半发现不对要改签名,那你得把光标挪回那行改(如果你写的是 C/C++ 这种那恭喜你要改两次 ...),哪怕你只是做一个 prototype,而在图形化的环境里面,我就只要把“Input Node”拖进来,然后连到需要用这个参数的地方就行了。

这种模式有什么实际应用?我也不是十分清楚,但是如果曾经在基础设施稍微好一点的公司干过的话,应该会见过类似“配置流程”之类的东西,有一点相似之处。给几个 hint:
* 如果目标使用环境本身就属于无法离开定位设备的情况,这种模式有天然的优势( Vim 等文本操作模式的全键盘操作无法实现)。
* 图形化的界面对非程序员(包括且不限于项目中的其他角色以及终端用户)更友好。
* 对没键盘 /键盘残废的触屏设备更友好。(虽然我个人认为这个还是要结合文本编程,也就是说键盘依然是很必要的)
2019-09-15 16:17:33 +08:00
回复了 shachengpo 创建的主题 程序员 程序员终究不是“终身职业”,窝慌了
@justforlook44444 我没说程序员是啊
2019-09-14 23:53:32 +08:00
回复了 shachengpo 创建的主题 程序员 程序员终究不是“终身职业”,窝慌了
@justforlook44444 我觉得在国内的语境下,“终身职业”并不一定包含“越老越值钱”的意思,更多的是“保本”,“稳定”的含义
2019-09-14 22:54:46 +08:00
回复了 shachengpo 创建的主题 程序员 程序员终究不是“终身职业”,窝慌了
我一直觉得习惯“终身职业”的人更适合进体制。任何体制外的工作都不是“终身职业”。
2019-09-14 11:41:39 +08:00
回复了 x97bgt 创建的主题 程序员 怎么提高使用 Windows 的工作效率?
微软最近在做 Win10 的 PowerToys,里面有个东西叫 FancyZones: https://github.com/microsoft/PowerToys/tree/master/src/modules/fancyzones

我不怎么用 Windows,不过看起来这东西能让 Windows 的窗口管理 better than better

至于终端,你暂时需要的是带 Tab 的终端模拟器 + tmux。
一个关键的问题是,无论 Win10 还是 macOS,默认设置下,不按 Win+Tab/Cmd+Tab 的话都是看不见不同窗口的标题名的,在任务栏 /Dock 上只能通过图标分辨窗口(而且 Windows 现在默认也像 mac 一样把多个同样的窗口 collapse 到同一个图标上),这导致一个很影响效率的问题,就是如果同一个应用开了多个同类型的窗口,基本不可能一键切换过去。

这个问题会出现在很多常用软件的常用使用场景中,比如多个浏览器窗口,多个终端窗口,多个 Explorer/Finder 窗口,多个编辑器 /IDE 窗口。多个 Office 窗口,多个 PDF 文件——这些都是非常常见的情况。
但是目前主流桌面操作系统的窗口管理机制,根本就没有为这种情况考虑,甚至人为地将“快速切换多个同类型”窗口的任务变得越来越复杂。(目前的桌面系统实际上更适合于“一个浏览器窗口、一个 Word 窗口、一个 PowerPoint 窗口、一个 Excel 窗口、一个 Outlook 窗口、一个 OneNote 窗口、一个 Skype 窗口”的这种场景)移动操作系统更不用说了,貌似 iPadOS 才刚开始做单个 App 多个实例共存。
我认为,不解决这个问题,那就免谈生产力。

不幸地是,所谓的“现代”桌面系统把这个问题完全推给了应用开发者。于是我们看到浏览器有自己的 Tab 系统,终端模拟器有自己的 Tab 系统,终端模拟器里面还可以嵌一个 Tab 系统,Excel 和 OneNote 有自己的 Tab 系统,文件管理器有自己的 Tab 系统,PDF 阅读器有自己的 Tab 系统,编辑器 /IDE 有自己的 Tab 系统,Photoshop 有自己的 Tab 系统,QQ/微信有自己的 Tab 系统 ...
桌面浏览器在世纪初开始引入 Tab,OS X 10.5 ( 09 年)的 Terminal 有了 Tab,10.9 ( 13 年)的 Finder 有了 Tab。最近的 Windows Terminal 作为 9012 年的产品理所当然一开始就有 Tab。
有报道说微软尝试基于 Edge (老的那个)在 Win10 上加入一个略微更 universal 的 Tab。我记得很久之前的 Windows,Explorer 既可以开本地文件夹也可以开网页,这个有点异曲同工,但或许是我记混了,不过确实有这样的产品——KDE 的 Konqueror 就既可以做文件管理器,也可以做浏览器,还有 Tab,虽然这俩东西应该都是历史了)可惜的是后来又说这个东西暂时不做了。
然后就没了 ...

每个软件独立的 Tab,只有两个好处:Tab 和软件本身的结合更紧密;以及桌面环境的开发者省事了。但是造成的问题:软件开发者需要做更多的工作,视觉上会出现不一致(只要看看 Chrome 的 Tab 改过多少版就知道 ...),功能也非常不一致,以及——至少一大部分常用软件,尽管有加 Tab 的需求,却根本就不支持 Tab。
Windows 的 Explorer 到现在没一个官方的 Tab 系统,这导致我到现在一直觉得 Explorer 是个半残的软件,Finder 则是最好用的 GUI 文件管理器(不考虑 bug 比较多的问题的话 ...)( Finder 另一个 killer feature 是“计算所有大小”)

统一 Tab 的另一个重要好处是 Tab 能像窗口一样被桌面环境统一管理,以及统一的搜索——浏览器和文本编辑器已经在做这件事,tmux、Emacs 早就能做到。不过这个其实没那么常用,“搜索”这个操作的成本还是比较高的。Emacs 生态环境有完善的 buffer 管理机制,包括以搜索为核心的操作逻辑——考虑到你可以把任何东西放进 Emacs 的 buffer 里面,这几乎相当于一个半成品的窗口管理器,但是缺少良好支持的好用的 Tab,我认为是 Emacs 的缺陷——如果我的目标 buffer 没有显示在当前 frame 里面,我就必须调起搜索才能找到,但是换在 vim 里面,可能就是 gt 一下的事情,Tab 在不少情况下有不可替代的作用。
again,据我所知,“现代”桌面操作系统目前只停留在搜索应用的阶段,我觉得我们并不能他们指望在这方面能有什么作为。
1 ... 75  76  77  78  79  80  81  82  83  84 ... 123  
关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   4869 人在线   最高记录 6679   ·     Select Language
创意工作者们的社区
World is powered by solitude
VERSION: 3.9.8.5 · 52ms · UTC 09:54 · PVG 17:54 · LAX 01:54 · JFK 04:54
Developed with CodeLauncher
♥ Do have faith in what you're doing.